Skip to content

Commit 0d03e9d

Browse files
heiherchenhuacai
authored andcommitted
LoongArch: Add guard for the larch_insn_gen_xxx functions
Add guard for the larch_insn_gen_xxx functions to verify whether the immediate operand is within the acceptable range. Signed-off-by: WANG Rui <wangrui@loongson.cn> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
1 parent d7c2496 commit 0d03e9d

3 files changed

Lines changed: 34 additions & 5 deletions

File tree

arch/loongarch/include/asm/inst.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#ifndef _ASM_INST_H
66
#define _ASM_INST_H
77

8+
#include <linux/bitops.h>
89
#include <linux/types.h>
910
#include <asm/asm.h>
1011
#include <asm/ptrace.h>
@@ -15,14 +16,22 @@
1516
#define ADDR_IMMMASK_LU52ID 0xFFF0000000000000
1617
#define ADDR_IMMMASK_LU32ID 0x000FFFFF00000000
1718
#define ADDR_IMMMASK_LU12IW 0x00000000FFFFF000
19+
#define ADDR_IMMMASK_ORI 0x0000000000000FFF
1820
#define ADDR_IMMMASK_ADDU16ID 0x00000000FFFF0000
1921

2022
#define ADDR_IMMSHIFT_LU52ID 52
23+
#define ADDR_IMMSBIDX_LU52ID 11
2124
#define ADDR_IMMSHIFT_LU32ID 32
25+
#define ADDR_IMMSBIDX_LU32ID 19
2226
#define ADDR_IMMSHIFT_LU12IW 12
27+
#define ADDR_IMMSBIDX_LU12IW 19
28+
#define ADDR_IMMSHIFT_ORI 0
29+
#define ADDR_IMMSBIDX_ORI 63
2330
#define ADDR_IMMSHIFT_ADDU16ID 16
31+
#define ADDR_IMMSBIDX_ADDU16ID 15
2432

25-
#define ADDR_IMM(addr, INSN) ((addr & ADDR_IMMMASK_##INSN) >> ADDR_IMMSHIFT_##INSN)
33+
#define ADDR_IMM(addr, INSN) \
34+
(sign_extend64(((addr & ADDR_IMMMASK_##INSN) >> ADDR_IMMSHIFT_##INSN), ADDR_IMMSBIDX_##INSN))
2635

2736
enum reg0i15_op {
2837
break_op = 0x54,
@@ -449,7 +458,7 @@ u32 larch_insn_gen_move(enum loongarch_gpr rd, enum loongarch_gpr rj);
449458
u32 larch_insn_gen_lu12iw(enum loongarch_gpr rd, int imm);
450459
u32 larch_insn_gen_lu32id(enum loongarch_gpr rd, int imm);
451460
u32 larch_insn_gen_lu52id(enum loongarch_gpr rd, enum loongarch_gpr rj, int imm);
452-
u32 larch_insn_gen_jirl(enum loongarch_gpr rd, enum loongarch_gpr rj, unsigned long pc, unsigned long dest);
461+
u32 larch_insn_gen_jirl(enum loongarch_gpr rd, enum loongarch_gpr rj, int imm);
453462

454463
static inline bool signed_imm_check(long val, unsigned int bit)
455464
{

arch/loongarch/include/asm/module.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ static inline struct plt_entry emit_plt_entry(unsigned long val)
5555
lu12iw = larch_insn_gen_lu12iw(LOONGARCH_GPR_T1, ADDR_IMM(val, LU12IW));
5656
lu32id = larch_insn_gen_lu32id(LOONGARCH_GPR_T1, ADDR_IMM(val, LU32ID));
5757
lu52id = larch_insn_gen_lu52id(LOONGARCH_GPR_T1, LOONGARCH_GPR_T1, ADDR_IMM(val, LU52ID));
58-
jirl = larch_insn_gen_jirl(0, LOONGARCH_GPR_T1, 0, (val & 0xfff));
58+
jirl = larch_insn_gen_jirl(0, LOONGARCH_GPR_T1, ADDR_IMM(val, ORI));
5959

6060
return (struct plt_entry) { lu12iw, lu32id, lu52id, jirl };
6161
}

arch/loongarch/kernel/inst.c

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,11 @@ u32 larch_insn_gen_lu12iw(enum loongarch_gpr rd, int imm)
226226
{
227227
union loongarch_instruction insn;
228228

229+
if (imm < -SZ_512K || imm >= SZ_512K) {
230+
pr_warn("The generated lu12i.w instruction is out of range.\n");
231+
return INSN_BREAK;
232+
}
233+
229234
emit_lu12iw(&insn, rd, imm);
230235

231236
return insn.word;
@@ -235,6 +240,11 @@ u32 larch_insn_gen_lu32id(enum loongarch_gpr rd, int imm)
235240
{
236241
union loongarch_instruction insn;
237242

243+
if (imm < -SZ_512K || imm >= SZ_512K) {
244+
pr_warn("The generated lu32i.d instruction is out of range.\n");
245+
return INSN_BREAK;
246+
}
247+
238248
emit_lu32id(&insn, rd, imm);
239249

240250
return insn.word;
@@ -244,16 +254,26 @@ u32 larch_insn_gen_lu52id(enum loongarch_gpr rd, enum loongarch_gpr rj, int imm)
244254
{
245255
union loongarch_instruction insn;
246256

257+
if (imm < -SZ_2K || imm >= SZ_2K) {
258+
pr_warn("The generated lu52i.d instruction is out of range.\n");
259+
return INSN_BREAK;
260+
}
261+
247262
emit_lu52id(&insn, rd, rj, imm);
248263

249264
return insn.word;
250265
}
251266

252-
u32 larch_insn_gen_jirl(enum loongarch_gpr rd, enum loongarch_gpr rj, unsigned long pc, unsigned long dest)
267+
u32 larch_insn_gen_jirl(enum loongarch_gpr rd, enum loongarch_gpr rj, int imm)
253268
{
254269
union loongarch_instruction insn;
255270

256-
emit_jirl(&insn, rj, rd, (dest - pc) >> 2);
271+
if ((imm & 3) || imm < -SZ_128K || imm >= SZ_128K) {
272+
pr_warn("The generated jirl instruction is out of range.\n");
273+
return INSN_BREAK;
274+
}
275+
276+
emit_jirl(&insn, rj, rd, imm >> 2);
257277

258278
return insn.word;
259279
}

0 commit comments

Comments
 (0)