Loading arch/arm64/Kconfig +1 −1 Original line number Original line Diff line number Diff line Loading @@ -910,7 +910,7 @@ config RANDOMIZE_BASE config RANDOMIZE_MODULE_REGION_FULL config RANDOMIZE_MODULE_REGION_FULL bool "Randomize the module region independently from the core kernel" bool "Randomize the module region independently from the core kernel" depends on RANDOMIZE_BASE depends on RANDOMIZE_BASE && !DYNAMIC_FTRACE default y default y help help Randomizes the location of the module region without considering the Randomizes the location of the module region without considering the Loading arch/arm64/kernel/insn.c +112 −53 Original line number Original line Diff line number Diff line Loading @@ -2,7 +2,7 @@ * Copyright (C) 2013 Huawei Ltd. * Copyright (C) 2013 Huawei Ltd. * Author: Jiang Liu <liuj97@gmail.com> * Author: Jiang Liu <liuj97@gmail.com> * * * Copyright (C) 2014 Zi Shen Lim <zlim.lnx@gmail.com> * Copyright (C) 2014-2016 Zi Shen Lim <zlim.lnx@gmail.com> * * * This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as Loading Loading @@ -364,6 +364,9 @@ u32 __kprobes aarch64_insn_encode_immediate(enum aarch64_insn_imm_type type, u32 immlo, immhi, mask; u32 immlo, immhi, mask; int shift; int shift; if (insn == AARCH64_BREAK_FAULT) return AARCH64_BREAK_FAULT; switch (type) { switch (type) { case AARCH64_INSN_IMM_ADR: case AARCH64_INSN_IMM_ADR: shift = 0; shift = 0; Loading @@ -378,7 +381,7 @@ u32 __kprobes aarch64_insn_encode_immediate(enum aarch64_insn_imm_type type, if (aarch64_get_imm_shift_mask(type, &mask, &shift) < 0) { if (aarch64_get_imm_shift_mask(type, &mask, &shift) < 0) { pr_err("aarch64_insn_encode_immediate: unknown immediate encoding %d\n", pr_err("aarch64_insn_encode_immediate: unknown immediate encoding %d\n", type); type); return 0; return AARCH64_BREAK_FAULT; } } } } Loading @@ -395,9 +398,12 @@ static u32 aarch64_insn_encode_register(enum aarch64_insn_register_type type, { { int shift; int shift; if (insn == AARCH64_BREAK_FAULT) return AARCH64_BREAK_FAULT; if (reg < AARCH64_INSN_REG_0 || reg > AARCH64_INSN_REG_SP) { if (reg < AARCH64_INSN_REG_0 || reg > AARCH64_INSN_REG_SP) { pr_err("%s: unknown register encoding %d\n", __func__, reg); pr_err("%s: unknown register encoding %d\n", __func__, reg); return 0; return AARCH64_BREAK_FAULT; } } switch (type) { switch (type) { Loading @@ -418,7 +424,7 @@ static u32 aarch64_insn_encode_register(enum aarch64_insn_register_type type, default: default: pr_err("%s: unknown register type encoding %d\n", __func__, pr_err("%s: unknown register type encoding %d\n", __func__, type); type); return 0; return AARCH64_BREAK_FAULT; } } insn &= ~(GENMASK(4, 0) << shift); insn &= ~(GENMASK(4, 0) << shift); Loading Loading @@ -447,7 +453,7 @@ static u32 aarch64_insn_encode_ldst_size(enum aarch64_insn_size_type type, break; break; default: default: pr_err("%s: unknown size encoding %d\n", __func__, type); pr_err("%s: unknown size encoding %d\n", __func__, type); return 0; return AARCH64_BREAK_FAULT; } } insn &= ~GENMASK(31, 30); insn &= ~GENMASK(31, 30); Loading @@ -461,14 +467,17 @@ static inline long branch_imm_common(unsigned long pc, unsigned long addr, { { long offset; long offset; /* if ((pc & 0x3) || (addr & 0x3)) { * PC: A 64-bit Program Counter holding the address of the current pr_err("%s: A64 instructions must be word aligned\n", __func__); * instruction. A64 instructions must be word-aligned. return range; */ } BUG_ON((pc & 0x3) || (addr & 0x3)); offset = ((long)addr - (long)pc); offset = ((long)addr - (long)pc); BUG_ON(offset < -range || offset >= range); if (offset < -range || offset >= range) { pr_err("%s: offset out of range\n", __func__); return range; } return offset; return offset; } } Loading @@ -485,6 +494,8 @@ u32 __kprobes aarch64_insn_gen_branch_imm(unsigned long pc, unsigned long addr, * texts are within +/-128M. * texts are within +/-128M. */ */ offset = branch_imm_common(pc, addr, SZ_128M); offset = branch_imm_common(pc, addr, SZ_128M); if (offset >= SZ_128M) return AARCH64_BREAK_FAULT; switch (type) { switch (type) { case AARCH64_INSN_BRANCH_LINK: case AARCH64_INSN_BRANCH_LINK: Loading @@ -494,7 +505,7 @@ u32 __kprobes aarch64_insn_gen_branch_imm(unsigned long pc, unsigned long addr, insn = aarch64_insn_get_b_value(); insn = aarch64_insn_get_b_value(); break; break; default: default: BUG_ON(1); pr_err("%s: unknown branch encoding %d\n", __func__, type); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading @@ -511,6 +522,8 @@ u32 aarch64_insn_gen_comp_branch_imm(unsigned long pc, unsigned long addr, long offset; long offset; offset = branch_imm_common(pc, addr, SZ_1M); offset = branch_imm_common(pc, addr, SZ_1M); if (offset >= SZ_1M) return AARCH64_BREAK_FAULT; switch (type) { switch (type) { case AARCH64_INSN_BRANCH_COMP_ZERO: case AARCH64_INSN_BRANCH_COMP_ZERO: Loading @@ -520,7 +533,7 @@ u32 aarch64_insn_gen_comp_branch_imm(unsigned long pc, unsigned long addr, insn = aarch64_insn_get_cbnz_value(); insn = aarch64_insn_get_cbnz_value(); break; break; default: default: BUG_ON(1); pr_err("%s: unknown branch encoding %d\n", __func__, type); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading @@ -531,7 +544,7 @@ u32 aarch64_insn_gen_comp_branch_imm(unsigned long pc, unsigned long addr, insn |= AARCH64_INSN_SF_BIT; insn |= AARCH64_INSN_SF_BIT; break; break; default: default: BUG_ON(1); pr_err("%s: unknown variant encoding %d\n", __func__, variant); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading @@ -551,7 +564,10 @@ u32 aarch64_insn_gen_cond_branch_imm(unsigned long pc, unsigned long addr, insn = aarch64_insn_get_bcond_value(); insn = aarch64_insn_get_bcond_value(); BUG_ON(cond < AARCH64_INSN_COND_EQ || cond > AARCH64_INSN_COND_AL); if (cond < AARCH64_INSN_COND_EQ || cond > AARCH64_INSN_COND_AL) { pr_err("%s: unknown condition encoding %d\n", __func__, cond); return AARCH64_BREAK_FAULT; } insn |= cond; insn |= cond; return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_19, insn, return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_19, insn, Loading Loading @@ -584,7 +600,7 @@ u32 aarch64_insn_gen_branch_reg(enum aarch64_insn_register reg, insn = aarch64_insn_get_ret_value(); insn = aarch64_insn_get_ret_value(); break; break; default: default: BUG_ON(1); pr_err("%s: unknown branch encoding %d\n", __func__, type); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading @@ -607,7 +623,7 @@ u32 aarch64_insn_gen_load_store_reg(enum aarch64_insn_register reg, insn = aarch64_insn_get_str_reg_value(); insn = aarch64_insn_get_str_reg_value(); break; break; default: default: BUG_ON(1); pr_err("%s: unknown load/store encoding %d\n", __func__, type); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading Loading @@ -646,26 +662,30 @@ u32 aarch64_insn_gen_load_store_pair(enum aarch64_insn_register reg1, insn = aarch64_insn_get_stp_post_value(); insn = aarch64_insn_get_stp_post_value(); break; break; default: default: BUG_ON(1); pr_err("%s: unknown load/store encoding %d\n", __func__, type); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } switch (variant) { switch (variant) { case AARCH64_INSN_VARIANT_32BIT: case AARCH64_INSN_VARIANT_32BIT: /* offset must be multiples of 4 in the range [-256, 252] */ if ((offset & 0x3) || (offset < -256) || (offset > 252)) { BUG_ON(offset & 0x3); pr_err("%s: offset must be multiples of 4 in the range of [-256, 252] %d\n", BUG_ON(offset < -256 || offset > 252); __func__, offset); return AARCH64_BREAK_FAULT; } shift = 2; shift = 2; break; break; case AARCH64_INSN_VARIANT_64BIT: case AARCH64_INSN_VARIANT_64BIT: /* offset must be multiples of 8 in the range [-512, 504] */ if ((offset & 0x7) || (offset < -512) || (offset > 504)) { BUG_ON(offset & 0x7); pr_err("%s: offset must be multiples of 8 in the range of [-512, 504] %d\n", BUG_ON(offset < -512 || offset > 504); __func__, offset); return AARCH64_BREAK_FAULT; } shift = 3; shift = 3; insn |= AARCH64_INSN_SF_BIT; insn |= AARCH64_INSN_SF_BIT; break; break; default: default: BUG_ON(1); pr_err("%s: unknown variant encoding %d\n", __func__, variant); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading Loading @@ -703,7 +723,7 @@ u32 aarch64_insn_gen_add_sub_imm(enum aarch64_insn_register dst, insn = aarch64_insn_get_subs_imm_value(); insn = aarch64_insn_get_subs_imm_value(); break; break; default: default: BUG_ON(1); pr_err("%s: unknown add/sub encoding %d\n", __func__, type); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading @@ -714,11 +734,14 @@ u32 aarch64_insn_gen_add_sub_imm(enum aarch64_insn_register dst, insn |= AARCH64_INSN_SF_BIT; insn |= AARCH64_INSN_SF_BIT; break; break; default: default: BUG_ON(1); pr_err("%s: unknown variant encoding %d\n", __func__, variant); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } BUG_ON(imm & ~(SZ_4K - 1)); if (imm & ~(SZ_4K - 1)) { pr_err("%s: invalid immediate encoding %d\n", __func__, imm); return AARCH64_BREAK_FAULT; } insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst); insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst); Loading Loading @@ -747,7 +770,7 @@ u32 aarch64_insn_gen_bitfield(enum aarch64_insn_register dst, insn = aarch64_insn_get_sbfm_value(); insn = aarch64_insn_get_sbfm_value(); break; break; default: default: BUG_ON(1); pr_err("%s: unknown bitfield encoding %d\n", __func__, type); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading @@ -760,12 +783,18 @@ u32 aarch64_insn_gen_bitfield(enum aarch64_insn_register dst, mask = GENMASK(5, 0); mask = GENMASK(5, 0); break; break; default: default: BUG_ON(1); pr_err("%s: unknown variant encoding %d\n", __func__, variant); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } BUG_ON(immr & ~mask); if (immr & ~mask) { BUG_ON(imms & ~mask); pr_err("%s: invalid immr encoding %d\n", __func__, immr); return AARCH64_BREAK_FAULT; } if (imms & ~mask) { pr_err("%s: invalid imms encoding %d\n", __func__, imms); return AARCH64_BREAK_FAULT; } insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst); insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst); Loading Loading @@ -794,23 +823,33 @@ u32 aarch64_insn_gen_movewide(enum aarch64_insn_register dst, insn = aarch64_insn_get_movn_value(); insn = aarch64_insn_get_movn_value(); break; break; default: default: BUG_ON(1); pr_err("%s: unknown movewide encoding %d\n", __func__, type); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } BUG_ON(imm & ~(SZ_64K - 1)); if (imm & ~(SZ_64K - 1)) { pr_err("%s: invalid immediate encoding %d\n", __func__, imm); return AARCH64_BREAK_FAULT; } switch (variant) { switch (variant) { case AARCH64_INSN_VARIANT_32BIT: case AARCH64_INSN_VARIANT_32BIT: BUG_ON(shift != 0 && shift != 16); if (shift != 0 && shift != 16) { pr_err("%s: invalid shift encoding %d\n", __func__, shift); return AARCH64_BREAK_FAULT; } break; break; case AARCH64_INSN_VARIANT_64BIT: case AARCH64_INSN_VARIANT_64BIT: insn |= AARCH64_INSN_SF_BIT; insn |= AARCH64_INSN_SF_BIT; BUG_ON(shift != 0 && shift != 16 && shift != 32 && if (shift != 0 && shift != 16 && shift != 32 && shift != 48) { shift != 48); pr_err("%s: invalid shift encoding %d\n", __func__, shift); return AARCH64_BREAK_FAULT; } break; break; default: default: BUG_ON(1); pr_err("%s: unknown variant encoding %d\n", __func__, variant); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading Loading @@ -844,20 +883,28 @@ u32 aarch64_insn_gen_add_sub_shifted_reg(enum aarch64_insn_register dst, insn = aarch64_insn_get_subs_value(); insn = aarch64_insn_get_subs_value(); break; break; default: default: BUG_ON(1); pr_err("%s: unknown add/sub encoding %d\n", __func__, type); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } switch (variant) { switch (variant) { case AARCH64_INSN_VARIANT_32BIT: case AARCH64_INSN_VARIANT_32BIT: BUG_ON(shift & ~(SZ_32 - 1)); if (shift & ~(SZ_32 - 1)) { pr_err("%s: invalid shift encoding %d\n", __func__, shift); return AARCH64_BREAK_FAULT; } break; break; case AARCH64_INSN_VARIANT_64BIT: case AARCH64_INSN_VARIANT_64BIT: insn |= AARCH64_INSN_SF_BIT; insn |= AARCH64_INSN_SF_BIT; BUG_ON(shift & ~(SZ_64 - 1)); if (shift & ~(SZ_64 - 1)) { pr_err("%s: invalid shift encoding %d\n", __func__, shift); return AARCH64_BREAK_FAULT; } break; break; default: default: BUG_ON(1); pr_err("%s: unknown variant encoding %d\n", __func__, variant); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading Loading @@ -886,11 +933,15 @@ u32 aarch64_insn_gen_data1(enum aarch64_insn_register dst, insn = aarch64_insn_get_rev32_value(); insn = aarch64_insn_get_rev32_value(); break; break; case AARCH64_INSN_DATA1_REVERSE_64: case AARCH64_INSN_DATA1_REVERSE_64: BUG_ON(variant != AARCH64_INSN_VARIANT_64BIT); if (variant != AARCH64_INSN_VARIANT_64BIT) { pr_err("%s: invalid variant for reverse64 %d\n", __func__, variant); return AARCH64_BREAK_FAULT; } insn = aarch64_insn_get_rev64_value(); insn = aarch64_insn_get_rev64_value(); break; break; default: default: BUG_ON(1); pr_err("%s: unknown data1 encoding %d\n", __func__, type); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading @@ -901,7 +952,7 @@ u32 aarch64_insn_gen_data1(enum aarch64_insn_register dst, insn |= AARCH64_INSN_SF_BIT; insn |= AARCH64_INSN_SF_BIT; break; break; default: default: BUG_ON(1); pr_err("%s: unknown variant encoding %d\n", __func__, variant); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading Loading @@ -938,7 +989,7 @@ u32 aarch64_insn_gen_data2(enum aarch64_insn_register dst, insn = aarch64_insn_get_rorv_value(); insn = aarch64_insn_get_rorv_value(); break; break; default: default: BUG_ON(1); pr_err("%s: unknown data2 encoding %d\n", __func__, type); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading @@ -949,7 +1000,7 @@ u32 aarch64_insn_gen_data2(enum aarch64_insn_register dst, insn |= AARCH64_INSN_SF_BIT; insn |= AARCH64_INSN_SF_BIT; break; break; default: default: BUG_ON(1); pr_err("%s: unknown variant encoding %d\n", __func__, variant); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading Loading @@ -977,7 +1028,7 @@ u32 aarch64_insn_gen_data3(enum aarch64_insn_register dst, insn = aarch64_insn_get_msub_value(); insn = aarch64_insn_get_msub_value(); break; break; default: default: BUG_ON(1); pr_err("%s: unknown data3 encoding %d\n", __func__, type); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading @@ -988,7 +1039,7 @@ u32 aarch64_insn_gen_data3(enum aarch64_insn_register dst, insn |= AARCH64_INSN_SF_BIT; insn |= AARCH64_INSN_SF_BIT; break; break; default: default: BUG_ON(1); pr_err("%s: unknown variant encoding %d\n", __func__, variant); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading Loading @@ -1038,20 +1089,28 @@ u32 aarch64_insn_gen_logical_shifted_reg(enum aarch64_insn_register dst, insn = aarch64_insn_get_bics_value(); insn = aarch64_insn_get_bics_value(); break; break; default: default: BUG_ON(1); pr_err("%s: unknown logical encoding %d\n", __func__, type); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } switch (variant) { switch (variant) { case AARCH64_INSN_VARIANT_32BIT: case AARCH64_INSN_VARIANT_32BIT: BUG_ON(shift & ~(SZ_32 - 1)); if (shift & ~(SZ_32 - 1)) { pr_err("%s: invalid shift encoding %d\n", __func__, shift); return AARCH64_BREAK_FAULT; } break; break; case AARCH64_INSN_VARIANT_64BIT: case AARCH64_INSN_VARIANT_64BIT: insn |= AARCH64_INSN_SF_BIT; insn |= AARCH64_INSN_SF_BIT; BUG_ON(shift & ~(SZ_64 - 1)); if (shift & ~(SZ_64 - 1)) { pr_err("%s: invalid shift encoding %d\n", __func__, shift); return AARCH64_BREAK_FAULT; } break; break; default: default: BUG_ON(1); pr_err("%s: unknown variant encoding %d\n", __func__, variant); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading Loading
arch/arm64/Kconfig +1 −1 Original line number Original line Diff line number Diff line Loading @@ -910,7 +910,7 @@ config RANDOMIZE_BASE config RANDOMIZE_MODULE_REGION_FULL config RANDOMIZE_MODULE_REGION_FULL bool "Randomize the module region independently from the core kernel" bool "Randomize the module region independently from the core kernel" depends on RANDOMIZE_BASE depends on RANDOMIZE_BASE && !DYNAMIC_FTRACE default y default y help help Randomizes the location of the module region without considering the Randomizes the location of the module region without considering the Loading
arch/arm64/kernel/insn.c +112 −53 Original line number Original line Diff line number Diff line Loading @@ -2,7 +2,7 @@ * Copyright (C) 2013 Huawei Ltd. * Copyright (C) 2013 Huawei Ltd. * Author: Jiang Liu <liuj97@gmail.com> * Author: Jiang Liu <liuj97@gmail.com> * * * Copyright (C) 2014 Zi Shen Lim <zlim.lnx@gmail.com> * Copyright (C) 2014-2016 Zi Shen Lim <zlim.lnx@gmail.com> * * * This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as Loading Loading @@ -364,6 +364,9 @@ u32 __kprobes aarch64_insn_encode_immediate(enum aarch64_insn_imm_type type, u32 immlo, immhi, mask; u32 immlo, immhi, mask; int shift; int shift; if (insn == AARCH64_BREAK_FAULT) return AARCH64_BREAK_FAULT; switch (type) { switch (type) { case AARCH64_INSN_IMM_ADR: case AARCH64_INSN_IMM_ADR: shift = 0; shift = 0; Loading @@ -378,7 +381,7 @@ u32 __kprobes aarch64_insn_encode_immediate(enum aarch64_insn_imm_type type, if (aarch64_get_imm_shift_mask(type, &mask, &shift) < 0) { if (aarch64_get_imm_shift_mask(type, &mask, &shift) < 0) { pr_err("aarch64_insn_encode_immediate: unknown immediate encoding %d\n", pr_err("aarch64_insn_encode_immediate: unknown immediate encoding %d\n", type); type); return 0; return AARCH64_BREAK_FAULT; } } } } Loading @@ -395,9 +398,12 @@ static u32 aarch64_insn_encode_register(enum aarch64_insn_register_type type, { { int shift; int shift; if (insn == AARCH64_BREAK_FAULT) return AARCH64_BREAK_FAULT; if (reg < AARCH64_INSN_REG_0 || reg > AARCH64_INSN_REG_SP) { if (reg < AARCH64_INSN_REG_0 || reg > AARCH64_INSN_REG_SP) { pr_err("%s: unknown register encoding %d\n", __func__, reg); pr_err("%s: unknown register encoding %d\n", __func__, reg); return 0; return AARCH64_BREAK_FAULT; } } switch (type) { switch (type) { Loading @@ -418,7 +424,7 @@ static u32 aarch64_insn_encode_register(enum aarch64_insn_register_type type, default: default: pr_err("%s: unknown register type encoding %d\n", __func__, pr_err("%s: unknown register type encoding %d\n", __func__, type); type); return 0; return AARCH64_BREAK_FAULT; } } insn &= ~(GENMASK(4, 0) << shift); insn &= ~(GENMASK(4, 0) << shift); Loading Loading @@ -447,7 +453,7 @@ static u32 aarch64_insn_encode_ldst_size(enum aarch64_insn_size_type type, break; break; default: default: pr_err("%s: unknown size encoding %d\n", __func__, type); pr_err("%s: unknown size encoding %d\n", __func__, type); return 0; return AARCH64_BREAK_FAULT; } } insn &= ~GENMASK(31, 30); insn &= ~GENMASK(31, 30); Loading @@ -461,14 +467,17 @@ static inline long branch_imm_common(unsigned long pc, unsigned long addr, { { long offset; long offset; /* if ((pc & 0x3) || (addr & 0x3)) { * PC: A 64-bit Program Counter holding the address of the current pr_err("%s: A64 instructions must be word aligned\n", __func__); * instruction. A64 instructions must be word-aligned. return range; */ } BUG_ON((pc & 0x3) || (addr & 0x3)); offset = ((long)addr - (long)pc); offset = ((long)addr - (long)pc); BUG_ON(offset < -range || offset >= range); if (offset < -range || offset >= range) { pr_err("%s: offset out of range\n", __func__); return range; } return offset; return offset; } } Loading @@ -485,6 +494,8 @@ u32 __kprobes aarch64_insn_gen_branch_imm(unsigned long pc, unsigned long addr, * texts are within +/-128M. * texts are within +/-128M. */ */ offset = branch_imm_common(pc, addr, SZ_128M); offset = branch_imm_common(pc, addr, SZ_128M); if (offset >= SZ_128M) return AARCH64_BREAK_FAULT; switch (type) { switch (type) { case AARCH64_INSN_BRANCH_LINK: case AARCH64_INSN_BRANCH_LINK: Loading @@ -494,7 +505,7 @@ u32 __kprobes aarch64_insn_gen_branch_imm(unsigned long pc, unsigned long addr, insn = aarch64_insn_get_b_value(); insn = aarch64_insn_get_b_value(); break; break; default: default: BUG_ON(1); pr_err("%s: unknown branch encoding %d\n", __func__, type); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading @@ -511,6 +522,8 @@ u32 aarch64_insn_gen_comp_branch_imm(unsigned long pc, unsigned long addr, long offset; long offset; offset = branch_imm_common(pc, addr, SZ_1M); offset = branch_imm_common(pc, addr, SZ_1M); if (offset >= SZ_1M) return AARCH64_BREAK_FAULT; switch (type) { switch (type) { case AARCH64_INSN_BRANCH_COMP_ZERO: case AARCH64_INSN_BRANCH_COMP_ZERO: Loading @@ -520,7 +533,7 @@ u32 aarch64_insn_gen_comp_branch_imm(unsigned long pc, unsigned long addr, insn = aarch64_insn_get_cbnz_value(); insn = aarch64_insn_get_cbnz_value(); break; break; default: default: BUG_ON(1); pr_err("%s: unknown branch encoding %d\n", __func__, type); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading @@ -531,7 +544,7 @@ u32 aarch64_insn_gen_comp_branch_imm(unsigned long pc, unsigned long addr, insn |= AARCH64_INSN_SF_BIT; insn |= AARCH64_INSN_SF_BIT; break; break; default: default: BUG_ON(1); pr_err("%s: unknown variant encoding %d\n", __func__, variant); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading @@ -551,7 +564,10 @@ u32 aarch64_insn_gen_cond_branch_imm(unsigned long pc, unsigned long addr, insn = aarch64_insn_get_bcond_value(); insn = aarch64_insn_get_bcond_value(); BUG_ON(cond < AARCH64_INSN_COND_EQ || cond > AARCH64_INSN_COND_AL); if (cond < AARCH64_INSN_COND_EQ || cond > AARCH64_INSN_COND_AL) { pr_err("%s: unknown condition encoding %d\n", __func__, cond); return AARCH64_BREAK_FAULT; } insn |= cond; insn |= cond; return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_19, insn, return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_19, insn, Loading Loading @@ -584,7 +600,7 @@ u32 aarch64_insn_gen_branch_reg(enum aarch64_insn_register reg, insn = aarch64_insn_get_ret_value(); insn = aarch64_insn_get_ret_value(); break; break; default: default: BUG_ON(1); pr_err("%s: unknown branch encoding %d\n", __func__, type); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading @@ -607,7 +623,7 @@ u32 aarch64_insn_gen_load_store_reg(enum aarch64_insn_register reg, insn = aarch64_insn_get_str_reg_value(); insn = aarch64_insn_get_str_reg_value(); break; break; default: default: BUG_ON(1); pr_err("%s: unknown load/store encoding %d\n", __func__, type); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading Loading @@ -646,26 +662,30 @@ u32 aarch64_insn_gen_load_store_pair(enum aarch64_insn_register reg1, insn = aarch64_insn_get_stp_post_value(); insn = aarch64_insn_get_stp_post_value(); break; break; default: default: BUG_ON(1); pr_err("%s: unknown load/store encoding %d\n", __func__, type); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } switch (variant) { switch (variant) { case AARCH64_INSN_VARIANT_32BIT: case AARCH64_INSN_VARIANT_32BIT: /* offset must be multiples of 4 in the range [-256, 252] */ if ((offset & 0x3) || (offset < -256) || (offset > 252)) { BUG_ON(offset & 0x3); pr_err("%s: offset must be multiples of 4 in the range of [-256, 252] %d\n", BUG_ON(offset < -256 || offset > 252); __func__, offset); return AARCH64_BREAK_FAULT; } shift = 2; shift = 2; break; break; case AARCH64_INSN_VARIANT_64BIT: case AARCH64_INSN_VARIANT_64BIT: /* offset must be multiples of 8 in the range [-512, 504] */ if ((offset & 0x7) || (offset < -512) || (offset > 504)) { BUG_ON(offset & 0x7); pr_err("%s: offset must be multiples of 8 in the range of [-512, 504] %d\n", BUG_ON(offset < -512 || offset > 504); __func__, offset); return AARCH64_BREAK_FAULT; } shift = 3; shift = 3; insn |= AARCH64_INSN_SF_BIT; insn |= AARCH64_INSN_SF_BIT; break; break; default: default: BUG_ON(1); pr_err("%s: unknown variant encoding %d\n", __func__, variant); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading Loading @@ -703,7 +723,7 @@ u32 aarch64_insn_gen_add_sub_imm(enum aarch64_insn_register dst, insn = aarch64_insn_get_subs_imm_value(); insn = aarch64_insn_get_subs_imm_value(); break; break; default: default: BUG_ON(1); pr_err("%s: unknown add/sub encoding %d\n", __func__, type); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading @@ -714,11 +734,14 @@ u32 aarch64_insn_gen_add_sub_imm(enum aarch64_insn_register dst, insn |= AARCH64_INSN_SF_BIT; insn |= AARCH64_INSN_SF_BIT; break; break; default: default: BUG_ON(1); pr_err("%s: unknown variant encoding %d\n", __func__, variant); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } BUG_ON(imm & ~(SZ_4K - 1)); if (imm & ~(SZ_4K - 1)) { pr_err("%s: invalid immediate encoding %d\n", __func__, imm); return AARCH64_BREAK_FAULT; } insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst); insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst); Loading Loading @@ -747,7 +770,7 @@ u32 aarch64_insn_gen_bitfield(enum aarch64_insn_register dst, insn = aarch64_insn_get_sbfm_value(); insn = aarch64_insn_get_sbfm_value(); break; break; default: default: BUG_ON(1); pr_err("%s: unknown bitfield encoding %d\n", __func__, type); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading @@ -760,12 +783,18 @@ u32 aarch64_insn_gen_bitfield(enum aarch64_insn_register dst, mask = GENMASK(5, 0); mask = GENMASK(5, 0); break; break; default: default: BUG_ON(1); pr_err("%s: unknown variant encoding %d\n", __func__, variant); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } BUG_ON(immr & ~mask); if (immr & ~mask) { BUG_ON(imms & ~mask); pr_err("%s: invalid immr encoding %d\n", __func__, immr); return AARCH64_BREAK_FAULT; } if (imms & ~mask) { pr_err("%s: invalid imms encoding %d\n", __func__, imms); return AARCH64_BREAK_FAULT; } insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst); insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RD, insn, dst); Loading Loading @@ -794,23 +823,33 @@ u32 aarch64_insn_gen_movewide(enum aarch64_insn_register dst, insn = aarch64_insn_get_movn_value(); insn = aarch64_insn_get_movn_value(); break; break; default: default: BUG_ON(1); pr_err("%s: unknown movewide encoding %d\n", __func__, type); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } BUG_ON(imm & ~(SZ_64K - 1)); if (imm & ~(SZ_64K - 1)) { pr_err("%s: invalid immediate encoding %d\n", __func__, imm); return AARCH64_BREAK_FAULT; } switch (variant) { switch (variant) { case AARCH64_INSN_VARIANT_32BIT: case AARCH64_INSN_VARIANT_32BIT: BUG_ON(shift != 0 && shift != 16); if (shift != 0 && shift != 16) { pr_err("%s: invalid shift encoding %d\n", __func__, shift); return AARCH64_BREAK_FAULT; } break; break; case AARCH64_INSN_VARIANT_64BIT: case AARCH64_INSN_VARIANT_64BIT: insn |= AARCH64_INSN_SF_BIT; insn |= AARCH64_INSN_SF_BIT; BUG_ON(shift != 0 && shift != 16 && shift != 32 && if (shift != 0 && shift != 16 && shift != 32 && shift != 48) { shift != 48); pr_err("%s: invalid shift encoding %d\n", __func__, shift); return AARCH64_BREAK_FAULT; } break; break; default: default: BUG_ON(1); pr_err("%s: unknown variant encoding %d\n", __func__, variant); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading Loading @@ -844,20 +883,28 @@ u32 aarch64_insn_gen_add_sub_shifted_reg(enum aarch64_insn_register dst, insn = aarch64_insn_get_subs_value(); insn = aarch64_insn_get_subs_value(); break; break; default: default: BUG_ON(1); pr_err("%s: unknown add/sub encoding %d\n", __func__, type); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } switch (variant) { switch (variant) { case AARCH64_INSN_VARIANT_32BIT: case AARCH64_INSN_VARIANT_32BIT: BUG_ON(shift & ~(SZ_32 - 1)); if (shift & ~(SZ_32 - 1)) { pr_err("%s: invalid shift encoding %d\n", __func__, shift); return AARCH64_BREAK_FAULT; } break; break; case AARCH64_INSN_VARIANT_64BIT: case AARCH64_INSN_VARIANT_64BIT: insn |= AARCH64_INSN_SF_BIT; insn |= AARCH64_INSN_SF_BIT; BUG_ON(shift & ~(SZ_64 - 1)); if (shift & ~(SZ_64 - 1)) { pr_err("%s: invalid shift encoding %d\n", __func__, shift); return AARCH64_BREAK_FAULT; } break; break; default: default: BUG_ON(1); pr_err("%s: unknown variant encoding %d\n", __func__, variant); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading Loading @@ -886,11 +933,15 @@ u32 aarch64_insn_gen_data1(enum aarch64_insn_register dst, insn = aarch64_insn_get_rev32_value(); insn = aarch64_insn_get_rev32_value(); break; break; case AARCH64_INSN_DATA1_REVERSE_64: case AARCH64_INSN_DATA1_REVERSE_64: BUG_ON(variant != AARCH64_INSN_VARIANT_64BIT); if (variant != AARCH64_INSN_VARIANT_64BIT) { pr_err("%s: invalid variant for reverse64 %d\n", __func__, variant); return AARCH64_BREAK_FAULT; } insn = aarch64_insn_get_rev64_value(); insn = aarch64_insn_get_rev64_value(); break; break; default: default: BUG_ON(1); pr_err("%s: unknown data1 encoding %d\n", __func__, type); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading @@ -901,7 +952,7 @@ u32 aarch64_insn_gen_data1(enum aarch64_insn_register dst, insn |= AARCH64_INSN_SF_BIT; insn |= AARCH64_INSN_SF_BIT; break; break; default: default: BUG_ON(1); pr_err("%s: unknown variant encoding %d\n", __func__, variant); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading Loading @@ -938,7 +989,7 @@ u32 aarch64_insn_gen_data2(enum aarch64_insn_register dst, insn = aarch64_insn_get_rorv_value(); insn = aarch64_insn_get_rorv_value(); break; break; default: default: BUG_ON(1); pr_err("%s: unknown data2 encoding %d\n", __func__, type); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading @@ -949,7 +1000,7 @@ u32 aarch64_insn_gen_data2(enum aarch64_insn_register dst, insn |= AARCH64_INSN_SF_BIT; insn |= AARCH64_INSN_SF_BIT; break; break; default: default: BUG_ON(1); pr_err("%s: unknown variant encoding %d\n", __func__, variant); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading Loading @@ -977,7 +1028,7 @@ u32 aarch64_insn_gen_data3(enum aarch64_insn_register dst, insn = aarch64_insn_get_msub_value(); insn = aarch64_insn_get_msub_value(); break; break; default: default: BUG_ON(1); pr_err("%s: unknown data3 encoding %d\n", __func__, type); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading @@ -988,7 +1039,7 @@ u32 aarch64_insn_gen_data3(enum aarch64_insn_register dst, insn |= AARCH64_INSN_SF_BIT; insn |= AARCH64_INSN_SF_BIT; break; break; default: default: BUG_ON(1); pr_err("%s: unknown variant encoding %d\n", __func__, variant); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading Loading @@ -1038,20 +1089,28 @@ u32 aarch64_insn_gen_logical_shifted_reg(enum aarch64_insn_register dst, insn = aarch64_insn_get_bics_value(); insn = aarch64_insn_get_bics_value(); break; break; default: default: BUG_ON(1); pr_err("%s: unknown logical encoding %d\n", __func__, type); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } switch (variant) { switch (variant) { case AARCH64_INSN_VARIANT_32BIT: case AARCH64_INSN_VARIANT_32BIT: BUG_ON(shift & ~(SZ_32 - 1)); if (shift & ~(SZ_32 - 1)) { pr_err("%s: invalid shift encoding %d\n", __func__, shift); return AARCH64_BREAK_FAULT; } break; break; case AARCH64_INSN_VARIANT_64BIT: case AARCH64_INSN_VARIANT_64BIT: insn |= AARCH64_INSN_SF_BIT; insn |= AARCH64_INSN_SF_BIT; BUG_ON(shift & ~(SZ_64 - 1)); if (shift & ~(SZ_64 - 1)) { pr_err("%s: invalid shift encoding %d\n", __func__, shift); return AARCH64_BREAK_FAULT; } break; break; default: default: BUG_ON(1); pr_err("%s: unknown variant encoding %d\n", __func__, variant); return AARCH64_BREAK_FAULT; return AARCH64_BREAK_FAULT; } } Loading