Skip to content

Commit f96b467

Browse files
committed
x86/insn: Use get_unaligned() instead of memcpy()
Use get_unaligned() instead of memcpy() to access potentially unaligned memory, which, when accessed through a pointer, leads to undefined behavior. get_unaligned() describes much better what is happening there anyway even if memcpy() does the job. In addition, since perf tool builds with -Werror, it would fire with: util/intel-pt-decoder/../../../arch/x86/lib/insn.c: In function '__insn_get_emulate_prefix': tools/include/../include/asm-generic/unaligned.h:10:15: error: packed attribute is unnecessary [-Werror=packed] 10 | const struct { type x; } __packed *__pptr = (typeof(__pptr))(ptr); \ because -Werror=packed would complain if the packed attribute would have no effect on the layout of the structure. In this case, that is intentional so disable the warning only for that compilation unit. That part is Reported-by: Stephen Rothwell <[email protected]> No functional changes. Fixes: 5ba1071 ("x86/insn, tools/x86: Fix undefined behavior due to potential unaligned accesses") Suggested-by: Linus Torvalds <[email protected]> Signed-off-by: Borislav Petkov <[email protected]> Acked-by: Masami Hiramatsu <[email protected]> Tested-by: Stephen Rothwell <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent ef775a0 commit f96b467

File tree

4 files changed

+31
-4
lines changed

4 files changed

+31
-4
lines changed

arch/x86/lib/insn.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#endif
1414
#include <asm/inat.h> /*__ignore_sync_check__ */
1515
#include <asm/insn.h> /* __ignore_sync_check__ */
16+
#include <asm/unaligned.h> /* __ignore_sync_check__ */
1617

1718
#include <linux/errno.h>
1819
#include <linux/kconfig.h>
@@ -37,10 +38,10 @@
3738
((insn)->next_byte + sizeof(t) + n <= (insn)->end_kaddr)
3839

3940
#define __get_next(t, insn) \
40-
({ t r; memcpy(&r, insn->next_byte, sizeof(t)); insn->next_byte += sizeof(t); leXX_to_cpu(t, r); })
41+
({ t r = get_unaligned((t *)(insn)->next_byte); (insn)->next_byte += sizeof(t); leXX_to_cpu(t, r); })
4142

4243
#define __peek_nbyte_next(t, insn, n) \
43-
({ t r; memcpy(&r, (insn)->next_byte + n, sizeof(t)); leXX_to_cpu(t, r); })
44+
({ t r = get_unaligned((t *)(insn)->next_byte + n); leXX_to_cpu(t, r); })
4445

4546
#define get_next(t, insn) \
4647
({ if (unlikely(!validate_next(t, insn, 0))) goto err_out; __get_next(t, insn); })

tools/arch/x86/lib/insn.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#endif
1414
#include "../include/asm/inat.h" /* __ignore_sync_check__ */
1515
#include "../include/asm/insn.h" /* __ignore_sync_check__ */
16+
#include "../include/asm-generic/unaligned.h" /* __ignore_sync_check__ */
1617

1718
#include <linux/errno.h>
1819
#include <linux/kconfig.h>
@@ -37,10 +38,10 @@
3738
((insn)->next_byte + sizeof(t) + n <= (insn)->end_kaddr)
3839

3940
#define __get_next(t, insn) \
40-
({ t r; memcpy(&r, insn->next_byte, sizeof(t)); insn->next_byte += sizeof(t); leXX_to_cpu(t, r); })
41+
({ t r = get_unaligned((t *)(insn)->next_byte); (insn)->next_byte += sizeof(t); leXX_to_cpu(t, r); })
4142

4243
#define __peek_nbyte_next(t, insn, n) \
43-
({ t r; memcpy(&r, (insn)->next_byte + n, sizeof(t)); leXX_to_cpu(t, r); })
44+
({ t r = get_unaligned((t *)(insn)->next_byte + n); leXX_to_cpu(t, r); })
4445

4546
#define get_next(t, insn) \
4647
({ if (unlikely(!validate_next(t, insn, 0))) goto err_out; __get_next(t, insn); })

tools/include/asm-generic/unaligned.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/* SPDX-License-Identifier: GPL-2.0-or-later */
2+
/*
3+
* Copied from the kernel sources to tools/perf/:
4+
*/
5+
6+
#ifndef __TOOLS_LINUX_ASM_GENERIC_UNALIGNED_H
7+
#define __TOOLS_LINUX_ASM_GENERIC_UNALIGNED_H
8+
9+
#define __get_unaligned_t(type, ptr) ({ \
10+
const struct { type x; } __packed *__pptr = (typeof(__pptr))(ptr); \
11+
__pptr->x; \
12+
})
13+
14+
#define __put_unaligned_t(type, val, ptr) do { \
15+
struct { type x; } __packed *__pptr = (typeof(__pptr))(ptr); \
16+
__pptr->x = (val); \
17+
} while (0)
18+
19+
#define get_unaligned(ptr) __get_unaligned_t(typeof(*(ptr)), (ptr))
20+
#define put_unaligned(val, ptr) __put_unaligned_t(typeof(*(ptr)), (val), (ptr))
21+
22+
#endif /* __TOOLS_LINUX_ASM_GENERIC_UNALIGNED_H */
23+

tools/perf/util/intel-pt-decoder/Build

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,5 @@ CFLAGS_intel-pt-insn-decoder.o += -I$(OUTPUT)util/intel-pt-decoder
1818
ifeq ($(CC_NO_CLANG), 1)
1919
CFLAGS_intel-pt-insn-decoder.o += -Wno-override-init
2020
endif
21+
22+
CFLAGS_intel-pt-insn-decoder.o += -Wno-packed

0 commit comments

Comments
 (0)