Skip to content

Commit dd0eb50

Browse files
mrutland-armctmarinas
authored andcommitted
arm64: probes: Cleanup kprobes endianness conversions
The core kprobes code uses kprobe_opcode_t for the in-memory representation of an instruction, using 'kprobe_opcode_t *' for XOL slots. As arm64 instructions are always little-endian 32-bit values, kprobes_opcode_t should be __le32, but at the moment kprobe_opcode_t is typedef'd to u32. Today there is no functional issue as we convert values via cpu_to_le32() and le32_to_cpu() where necessary, but these conversions are inconsistent with the types used, causing sparse warnings: | CHECK arch/arm64/kernel/probes/kprobes.c | arch/arm64/kernel/probes/kprobes.c:102:21: warning: cast to restricted __le32 | CHECK arch/arm64/kernel/probes/decode-insn.c | arch/arm64/kernel/probes/decode-insn.c:122:46: warning: cast to restricted __le32 | arch/arm64/kernel/probes/decode-insn.c:124:50: warning: cast to restricted __le32 | arch/arm64/kernel/probes/decode-insn.c:136:31: warning: cast to restricted __le32 Improve this by making kprobes_opcode_t a typedef for __le32 and consistently using this for pointers to executable instructions. With this change we can rely on the type system to tell us where conversions are necessary. Since kprobe::opcode is changed from u32 to __le32, the existing le32_to_cpu() converion moves from the point this is initialized (in arch_prepare_kprobe()) to the points this is consumed when passed to a handler or text patching function. As kprobe::opcode isn't altered or consumed elsewhere, this shouldn't result in a functional change. Signed-off-by: Mark Rutland <mark.rutland@arm.com> Cc: Will Deacon <will@kernel.org> Link: https://lore.kernel.org/r/20241008155851.801546-6-mark.rutland@arm.com Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
1 parent 6105c5d commit dd0eb50

File tree

3 files changed

+8
-7
lines changed

3 files changed

+8
-7
lines changed

arch/arm64/include/asm/probes.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ struct arch_probe_insn {
1616
probes_handler_t *handler;
1717
};
1818
#ifdef CONFIG_KPROBES
19-
typedef u32 kprobe_opcode_t;
19+
typedef __le32 kprobe_opcode_t;
2020
struct arch_specific_insn {
2121
struct arch_probe_insn api;
22-
probe_opcode_t *xol_insn;
22+
kprobe_opcode_t *xol_insn;
2323
/* restore address after step xol */
2424
unsigned long xol_restore;
2525
};

arch/arm64/kernel/probes/decode-insn.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ arm_kprobe_decode_insn(kprobe_opcode_t *addr, struct arch_specific_insn *asi)
134134
{
135135
enum probe_insn decoded;
136136
probe_opcode_t insn = le32_to_cpu(*addr);
137-
probe_opcode_t *scan_end = NULL;
137+
kprobe_opcode_t *scan_end = NULL;
138138
unsigned long size = 0, offset = 0;
139139
struct arch_probe_insn *api = &asi->api;
140140

arch/arm64/kernel/probes/kprobes.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ static void __kprobes arch_prepare_ss_slot(struct kprobe *p)
6464
* the BRK exception handler, so it is unnecessary to generate
6565
* Contex-Synchronization-Event via ISB again.
6666
*/
67-
aarch64_insn_patch_text_nosync(addr, p->opcode);
67+
aarch64_insn_patch_text_nosync(addr, le32_to_cpu(p->opcode));
6868
aarch64_insn_patch_text_nosync(addr + 1, BRK64_OPCODE_KPROBES_SS);
6969

7070
/*
@@ -85,7 +85,7 @@ static void __kprobes arch_simulate_insn(struct kprobe *p, struct pt_regs *regs)
8585
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
8686

8787
if (p->ainsn.api.handler)
88-
p->ainsn.api.handler((u32)p->opcode, (long)p->addr, regs);
88+
p->ainsn.api.handler(le32_to_cpu(p->opcode), (long)p->addr, regs);
8989

9090
/* single step simulated, now go for post processing */
9191
post_kprobe_handler(p, kcb, regs);
@@ -99,7 +99,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
9999
return -EINVAL;
100100

101101
/* copy instruction */
102-
p->opcode = le32_to_cpu(*p->addr);
102+
p->opcode = *p->addr;
103103

104104
if (search_exception_tables(probe_addr))
105105
return -EINVAL;
@@ -142,8 +142,9 @@ void __kprobes arch_arm_kprobe(struct kprobe *p)
142142
void __kprobes arch_disarm_kprobe(struct kprobe *p)
143143
{
144144
void *addr = p->addr;
145+
u32 insn = le32_to_cpu(p->opcode);
145146

146-
aarch64_insn_patch_text(&addr, &p->opcode, 1);
147+
aarch64_insn_patch_text(&addr, &insn, 1);
147148
}
148149

149150
void __kprobes arch_remove_kprobe(struct kprobe *p)

0 commit comments

Comments
 (0)