Message ID | be282f27ad808418c7475b51a00b4cb035f89a95.1687430631.git.christophe.leroy@csgroup.eu (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | powerpc/objtool: uaccess validation for PPC32 (v2) | expand |
On Thu, Jun 22, 2023 at 12:54:36PM +0200, Christophe Leroy wrote: > diff --git a/tools/objtool/check.c b/tools/objtool/check.c > index f850ab892ad5..8ac5711a055f 100644 > --- a/tools/objtool/check.c > +++ b/tools/objtool/check.c > @@ -218,6 +218,7 @@ static bool __dead_end_function(struct objtool_file *file, struct symbol *func, > "kthread_exit", > "kunit_try_catch_throw", > "lbug_with_loc", > + "longjmp", > "machine_real_restart", > "make_task_dead", > "mpt_halt_firmware", > @@ -230,7 +231,9 @@ static bool __dead_end_function(struct objtool_file *file, struct symbol *func, > "sev_es_terminate", > "snp_abort", > "start_kernel", > + "start_secondary_resume", > "stop_this_cpu", > + "unrecoverable_exception", > "usercopy_abort", > "x86_64_start_kernel", > "x86_64_start_reservations", Someone went and changed all that in tip/objtool/core :-) But perhaps, like the uaccess_safe_builtins[] array below, should we start marking sections so we can remember where stuff comes from later? > @@ -1335,6 +1338,8 @@ static const char *uaccess_safe_builtin[] = { > "rep_stos_alternative", > "rep_movs_alternative", > "__copy_user_nocache", > + "__copy_tofrom_user", > + "__arch_clear_user", > NULL > }; Do we want to rename the 'misc' sectino to 'x86' and start a 'ppc32' section there?
Hi Christophe, kernel test robot noticed the following build warnings: [auto build test WARNING on powerpc/next] [also build test WARNING on powerpc/fixes masahiroy-kbuild/for-next masahiroy-kbuild/fixes linus/master v6.4-rc7] [cannot apply to next-20230622] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Christophe-Leroy/powerpc-kuap-Avoid-unnecessary-reads-of-MD_AP/20230622-185950 base: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next patch link: https://lore.kernel.org/r/be282f27ad808418c7475b51a00b4cb035f89a95.1687430631.git.christophe.leroy%40csgroup.eu patch subject: [PATCH v2 14/14] powerpc: Implement UACCESS validation on PPC32 config: powerpc-randconfig-r025-20230622 (https://download.01.org/0day-ci/archive/20230623/202306230353.iPqv57lK-lkp@intel.com/config) compiler: powerpc-linux-gcc (GCC) 12.3.0 reproduce: (https://download.01.org/0day-ci/archive/20230623/202306230353.iPqv57lK-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202306230353.iPqv57lK-lkp@intel.com/ All warnings (new ones prefixed by >>): lib/ubsan.c:307:6: warning: no previous prototype for '__ubsan_handle_type_mismatch' [-Wmissing-prototypes] 307 | void __ubsan_handle_type_mismatch(struct type_mismatch_data *data, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ >> lib/ubsan.o: warning: objtool: ubsan_type_mismatch_common+0x24: UACCESS-safe disables UACCESS lib/ubsan.o: warning: objtool: __ubsan_handle_type_mismatch+0x54: call to _restgpr_30_x() with UACCESS enabled lib/ubsan.o: warning: objtool: __ubsan_handle_type_mismatch_v1+0x5c: call to _restgpr_30_x() with UACCESS enabled lib/ubsan.o: warning: objtool: __ubsan_handle_load_invalid_value+0x28: call to memset() with UACCESS enabled lib/ubsan.o: warning: objtool: __ubsan_handle_shift_out_of_bounds+0x34: call to memset() with UACCESS enabled -- >> arch/powerpc/kernel/ptrace/ptrace-view.o: warning: objtool: gpr32_set_common+0x2b8: redundant UACCESS disable objdump-func vmlinux.o ubsan_type_mismatch_common: 0000 00000000 <ubsan_type_mismatch_common>: 0000 0: 94 21 ff e0 stwu r1,-32(r1) 0004 4: 7c 08 02 a6 mflr r0 0008 8: bf 61 00 0c stmw r27,12(r1) 000c c: 7c 7f 1b 78 mr r31,r3 0010 10: 90 01 00 24 stw r0,36(r1) 0014 14: 7c 9e 23 78 mr r30,r4 0018 18: 48 00 00 01 bl 18 <ubsan_type_mismatch_common+0x18> 18: R_PPC_REL24 __sanitizer_cov_trace_pc 001c 1c: 7f 90 0a a6 mfpid r28 0020 20: 39 20 00 00 li r9,0 0024 24: 7d 30 0b a6 mtpid r9 0028 28: 4c 00 01 2c isync 002c 2c: 2c 1e 00 00 cmpwi r30,0 0030 30: 40 e2 00 58 bne+ 88 <ubsan_type_mismatch_common+0x88> 0034 34: 48 00 00 01 bl 34 <ubsan_type_mismatch_common+0x34> 34: R_PPC_REL24 __sanitizer_cov_trace_pc 0038 38: 80 7f 00 00 lwz r3,0(r31) 003c 3c: 48 00 00 01 bl 3c <ubsan_type_mismatch_common+0x3c> 3c: R_PPC_REL24 .text.suppress_report 0040 40: 2c 03 00 00 cmpwi r3,0 0044 44: 40 e2 01 30 bne+ 174 <ubsan_type_mismatch_common+0x174> 0048 48: 48 00 00 01 bl 48 <ubsan_type_mismatch_common+0x48> 48: R_PPC_REL24 __sanitizer_cov_trace_pc 004c 4c: 80 7f 00 00 lwz r3,0(r31) 0050 50: 3c 80 00 00 lis r4,0 52: R_PPC_ADDR16_HA .rodata.ubsan_type_mismatch_common.str1.1 0054 54: 38 84 00 00 addi r4,r4,0 56: R_PPC_ADDR16_LO .rodata.ubsan_type_mismatch_common.str1.1 0058 58: 48 00 00 01 bl 58 <ubsan_type_mismatch_common+0x58> 58: R_PPC_REL24 .text.unlikely.ubsan_prologue 005c 5c: 89 3f 00 0c lbz r9,12(r31) 0060 60: 3d 40 00 00 lis r10,0 62: R_PPC_ADDR16_HA .rodata.type_check_kinds 0064 64: 80 bf 00 04 lwz r5,4(r31) 0068 68: 39 4a 00 00 addi r10,r10,0 6a: R_PPC_ADDR16_LO .rodata.type_check_kinds 006c 6c: 55 29 10 3a slwi r9,r9,2 0070 70: 7c 8a 48 2e lwzx r4,r10,r9 0074 74: 3c 60 00 00 lis r3,0 76: R_PPC_ADDR16_HA .rodata.ubsan_type_mismatch_common.str1.1+0xf 0078 78: 38 a5 00 04 addi r5,r5,4 007c 7c: 38 63 00 00 addi r3,r3,0 7e: R_PPC_ADDR16_LO .rodata.ubsan_type_mismatch_common.str1.1+0xf 0080 80: 48 00 00 01 bl 80 <ubsan_type_mismatch_common+0x80> 80: R_PPC_REL24 _printk 0084 84: 48 00 00 ec b 170 <ubsan_type_mismatch_common+0x170> 0088 88: 48 00 00 01 bl 88 <ubsan_type_mismatch_common+0x88> 88: R_PPC_REL24 __sanitizer_cov_trace_pc 008c 8c: 83 bf 00 08 lwz r29,8(r31) 0090 90: 83 7f 00 00 lwz r27,0(r31) 0094 94: 2c 1d 00 00 cmpwi r29,0 0098 98: 41 c2 00 78 beq- 110 <ubsan_type_mismatch_common+0x110> 009c 9c: 3b bd ff ff addi r29,r29,-1 00a0 a0: 48 00 00 01 bl a0 <ubsan_type_mismatch_common+0xa0> a0: R_PPC_REL24 __sanitizer_cov_trace_pc 00a4 a4: 7f bd f0 39 and. r29,r29,r30 00a8 a8: 41 e2 00 68 beq+ 110 <ubsan_type_mismatch_common+0x110> 00ac ac: 48 00 00 01 bl ac <ubsan_type_mismatch_common+0xac> ac: R_PPC_REL24 __sanitizer_cov_trace_pc 00b0 b0: 7f 63 db 78 mr r3,r27 00b4 b4: 48 00 00 01 bl b4 <ubsan_type_mismatch_common+0xb4> b4: R_PPC_REL24 .text.suppress_report 00b8 b8: 2c 03 00 00 cmpwi r3,0 00bc bc: 40 e2 00 b8 bne+ 174 <ubsan_type_mismatch_common+0x174> 00c0 c0: 48 00 00 01 bl c0 <ubsan_type_mismatch_common+0xc0> c0: R_PPC_REL24 __sanitizer_cov_trace_pc 00c4 c4: 80 7f 00 00 lwz r3,0(r31) 00c8 c8: 3c 80 00 00 lis r4,0 ca: R_PPC_ADDR16_HA .rodata.ubsan_type_mismatch_common.str1.1+0x2d 00cc cc: 38 84 00 00 addi r4,r4,0 ce: R_PPC_ADDR16_LO .rodata.ubsan_type_mismatch_common.str1.1+0x2d 00d0 d0: 48 00 00 01 bl d0 <ubsan_type_mismatch_common+0xd0> d0: R_PPC_REL24 .text.unlikely.ubsan_prologue 00d4 d4: 89 3f 00 0c lbz r9,12(r31) 00d8 d8: 3d 40 00 00 lis r10,0 da: R_PPC_ADDR16_HA .rodata.type_check_kinds 00dc dc: 80 df 00 04 lwz r6,4(r31) 00e0 e0: 39 4a 00 00 addi r10,r10,0 e2: R_PPC_ADDR16_LO .rodata.type_check_kinds 00e4 e4: 55 29 10 3a slwi r9,r9,2 00e8 e8: 7c 8a 48 2e lwzx r4,r10,r9 00ec ec: 3c 60 00 00 lis r3,0 ee: R_PPC_ADDR16_HA .rodata.ubsan_type_mismatch_common.str1.1+0x3f 00f0 f0: 38 c6 00 04 addi r6,r6,4 00f4 f4: 7f c5 f3 78 mr r5,r30 00f8 f8: 38 63 00 00 addi r3,r3,0 fa: R_PPC_ADDR16_LO .rodata.ubsan_type_mismatch_common.str1.1+0x3f 00fc fc: 48 00 00 01 bl fc <ubsan_type_mismatch_common+0xfc> fc: R_PPC_REL24 _printk 0100 100: 3c 60 00 00 lis r3,0 102: R_PPC_ADDR16_HA .rodata.ubsan_type_mismatch_common.str1.1+0x67 0104 104: 80 9f 00 08 lwz r4,8(r31) 0108 108: 38 63 00 00 addi r3,r3,0 10a: R_PPC_ADDR16_LO .rodata.ubsan_type_mismatch_common.str1.1+0x67 010c 10c: 48 00 00 60 b 16c <ubsan_type_mismatch_common+0x16c> 0110 110: 48 00 00 01 bl 110 <ubsan_type_mismatch_common+0x110> 110: R_PPC_REL24 __sanitizer_cov_trace_pc 0114 114: 7f 63 db 78 mr r3,r27 0118 118: 48 00 00 01 bl 118 <ubsan_type_mismatch_common+0x118> 118: R_PPC_REL24 .text.suppress_report 011c 11c: 2c 03 00 00 cmpwi r3,0 0120 120: 40 e2 00 54 bne+ 174 <ubsan_type_mismatch_common+0x174> 0124 124: 48 00 00 01 bl 124 <ubsan_type_mismatch_common+0x124> 124: R_PPC_REL24 __sanitizer_cov_trace_pc 0128 128: 80 7f 00 00 lwz r3,0(r31) 012c 12c: 3c 80 00 00 lis r4,0 12e: R_PPC_ADDR16_HA .rodata.ubsan_type_mismatch_common.str1.1+0x8c 0130 130: 38 84 00 00 addi r4,r4,0 132: R_PPC_ADDR16_LO .rodata.ubsan_type_mismatch_common.str1.1+0x8c 0134 134: 48 00 00 01 bl 134 <ubsan_type_mismatch_common+0x134> 134: R_PPC_REL24 .text.unlikely.ubsan_prologue 0138 138: 89 3f 00 0c lbz r9,12(r31) 013c 13c: 3d 40 00 00 lis r10,0 13e: R_PPC_ADDR16_HA .rodata.type_check_kinds 0140 140: 39 4a 00 00 addi r10,r10,0 142: R_PPC_ADDR16_LO .rodata.type_check_kinds 0144 144: 55 29 10 3a slwi r9,r9,2 0148 148: 3c 60 00 00 lis r3,0 14a: R_PPC_ADDR16_HA .rodata.ubsan_type_mismatch_common.str1.1+0xa1 014c 14c: 7c 8a 48 2e lwzx r4,r10,r9 0150 150: 7f c5 f3 78 mr r5,r30 0154 154: 38 63 00 00 addi r3,r3,0 156: R_PPC_ADDR16_LO .rodata.ubsan_type_mismatch_common.str1.1+0xa1 0158 158: 48 00 00 01 bl 158 <ubsan_type_mismatch_common+0x158> 158: R_PPC_REL24 _printk 015c 15c: 80 9f 00 04 lwz r4,4(r31) 0160 160: 3c 60 00 00 lis r3,0 162: R_PPC_ADDR16_HA .rodata.ubsan_type_mismatch_common.str1.1+0xca 0164 164: 38 63 00 00 addi r3,r3,0 166: R_PPC_ADDR16_LO .rodata.ubsan_type_mismatch_common.str1.1+0xca 0168 168: 38 84 00 04 addi r4,r4,4 016c 16c: 48 00 00 01 bl 16c <ubsan_type_mismatch_common+0x16c> 16c: R_PPC_REL24 _printk 0170 170: 48 00 00 01 bl 170 <ubsan_type_mismatch_common+0x170> 170: R_PPC_REL24 .text.unlikely.ubsan_epilogue 0174 174: 48 00 00 01 bl 174 <ubsan_type_mismatch_common+0x174> 174: R_PPC_REL24 __sanitizer_cov_trace_pc 0178 178: 2c 1c 00 00 cmpwi r28,0 017c 17c: 41 e2 00 14 beq+ 190 <ubsan_type_mismatch_common+0x190> 0180 180: 48 00 00 01 bl 180 <ubsan_type_mismatch_common+0x180> 180: R_PPC_REL24 __sanitizer_cov_trace_pc 0184 184: 81 22 0e b4 lwz r9,3764(r2) 0188 188: 7d 30 0b a6 mtpid r9 018c 18c: 4c 00 01 2c isync 0190 190: 80 01 00 24 lwz r0,36(r1) 0194 194: 83 61 00 0c lwz r27,12(r1) 0198 198: 83 81 00 10 lwz r28,16(r1) 019c 19c: 83 a1 00 14 lwz r29,20(r1) 01a0 1a0: 7c 08 03 a6 mtlr r0 01a4 1a4: 83 c1 00 18 lwz r30,24(r1) 01a8 1a8: 83 e1 00 1c lwz r31,28(r1) 01ac 1ac: 38 21 00 20 addi r1,r1,32 01b0 1b0: 48 00 00 00 b 1b0 <ubsan_type_mismatch_common+0x1b0> 1b0: R_PPC_REL24 __sanitizer_cov_trace_pc
Hi Christophe,
kernel test robot noticed the following build warnings:
[auto build test WARNING on powerpc/next]
[also build test WARNING on powerpc/fixes masahiroy-kbuild/for-next masahiroy-kbuild/fixes linus/master v6.4-rc7]
[cannot apply to next-20230622]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Christophe-Leroy/powerpc-kuap-Avoid-unnecessary-reads-of-MD_AP/20230622-185950
base: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next
patch link: https://lore.kernel.org/r/be282f27ad808418c7475b51a00b4cb035f89a95.1687430631.git.christophe.leroy%40csgroup.eu
patch subject: [PATCH v2 14/14] powerpc: Implement UACCESS validation on PPC32
config: powerpc-allmodconfig (https://download.01.org/0day-ci/archive/20230623/202306230351.SpwvWyz3-lkp@intel.com/config)
compiler: powerpc-linux-gcc (GCC) 12.3.0
reproduce: (https://download.01.org/0day-ci/archive/20230623/202306230351.SpwvWyz3-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202306230351.SpwvWyz3-lkp@intel.com/
All warnings (new ones prefixed by >>):
arch/powerpc/platforms/powermac/smp.c:416:13: warning: no previous prototype for 'smp_psurge_take_timebase' [-Wmissing-prototypes]
416 | void __init smp_psurge_take_timebase(void)
| ^~~~~~~~~~~~~~~~~~~~~~~~
arch/powerpc/platforms/powermac/smp.c:432:13: warning: no previous prototype for 'smp_psurge_give_timebase' [-Wmissing-prototypes]
432 | void __init smp_psurge_give_timebase(void)
| ^~~~~~~~~~~~~~~~~~~~~~~~
>> arch/powerpc/platforms/powermac/smp.o: warning: objtool: .text.pmac_cpu_offline_self: unexpected end of section
Le 22/06/2023 à 13:56, Peter Zijlstra a écrit : > On Thu, Jun 22, 2023 at 12:54:36PM +0200, Christophe Leroy wrote: > >> diff --git a/tools/objtool/check.c b/tools/objtool/check.c >> index f850ab892ad5..8ac5711a055f 100644 >> --- a/tools/objtool/check.c >> +++ b/tools/objtool/check.c >> @@ -218,6 +218,7 @@ static bool __dead_end_function(struct objtool_file *file, struct symbol *func, >> "kthread_exit", >> "kunit_try_catch_throw", >> "lbug_with_loc", >> + "longjmp", >> "machine_real_restart", >> "make_task_dead", >> "mpt_halt_firmware", >> @@ -230,7 +231,9 @@ static bool __dead_end_function(struct objtool_file *file, struct symbol *func, >> "sev_es_terminate", >> "snp_abort", >> "start_kernel", >> + "start_secondary_resume", >> "stop_this_cpu", >> + "unrecoverable_exception", >> "usercopy_abort", >> "x86_64_start_kernel", >> "x86_64_start_reservations", > > Someone went and changed all that in tip/objtool/core :-) > > But perhaps, like the uaccess_safe_builtins[] array below, should we > start marking sections so we can remember where stuff comes from later? Or, now that it is a H file, maybe each arch could have its own H file for arch specific functions ? Then we'd get: diff --git a/tools/objtool/arch/powerpc/include/arch/noreturns.h b/tools/objtool/arch/powerpc/include/arch/noreturns.h new file mode 100644 index 000000000000..664f17d39026 --- /dev/null +++ b/tools/objtool/arch/powerpc/include/arch/noreturns.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * This is a (sorted!) list of all known __noreturn functions in arch/powerpc. + * It's needed for objtool to properly reverse-engineer the control flow graph. + * + * Yes, this is unfortunate. A better solution is in the works. + */ +NORETURN(longjmp) +NORETURN(start_secondary_resume) +NORETURN(unrecoverable_exception) diff --git a/tools/objtool/noreturns.h b/tools/objtool/noreturns.h index 1514e84d5cc4..f725ed37532d 100644 --- a/tools/objtool/noreturns.h +++ b/tools/objtool/noreturns.h @@ -1,5 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ +#include <arch/noreturns.h> + /* * This is a (sorted!) list of all known __noreturn functions in the kernel. * It's needed for objtool to properly reverse-engineer the control flow graph. > >> @@ -1335,6 +1338,8 @@ static const char *uaccess_safe_builtin[] = { >> "rep_stos_alternative", >> "rep_movs_alternative", >> "__copy_user_nocache", >> + "__copy_tofrom_user", >> + "__arch_clear_user", >> NULL >> }; > > Do we want to rename the 'misc' sectino to 'x86' and start a 'ppc32' > section there? > Sure. Then that would look like: diff --git a/tools/objtool/check.c b/tools/objtool/check.c index 2b61f8180bea..2d564d0e2ae1 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -1259,13 +1259,15 @@ static const char *uaccess_safe_builtin[] = { "stackleak_track_stack", /* misc */ "csum_partial_copy_generic", + "ftrace_likely_update", /* CONFIG_TRACE_BRANCH_PROFILING */ + /* misc x86 */ "copy_mc_fragile", "copy_mc_fragile_handle_tail", "copy_mc_enhanced_fast_string", - "ftrace_likely_update", /* CONFIG_TRACE_BRANCH_PROFILING */ "rep_stos_alternative", "rep_movs_alternative", "__copy_user_nocache", + /* misc powerpc */ "__copy_tofrom_user", "__arch_clear_user", NULL
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 8b955bc7b59f..8b613e520143 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -160,6 +160,7 @@ config PPC select ARCH_KEEP_MEMBLOCK select ARCH_MIGHT_HAVE_PC_PARPORT select ARCH_MIGHT_HAVE_PC_SERIO + select ARCH_OBJTOOL_SKIP_ASM select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT select ARCH_SPLIT_ARG64 if PPC32 @@ -258,6 +259,7 @@ config PPC select HAVE_OPTPROBES select HAVE_OBJTOOL if PPC32 || MPROFILE_KERNEL select HAVE_OBJTOOL_MCOUNT if HAVE_OBJTOOL + select HAVE_UACCESS_VALIDATION if HAVE_OBJTOOL && PPC_KUAP && PPC32 select HAVE_PERF_EVENTS select HAVE_PERF_EVENTS_NMI if PPC64 select HAVE_PERF_REGS diff --git a/arch/powerpc/include/asm/kup.h b/arch/powerpc/include/asm/kup.h index 132f1c7e1064..9f824cb93d8a 100644 --- a/arch/powerpc/include/asm/kup.h +++ b/arch/powerpc/include/asm/kup.h @@ -10,6 +10,8 @@ #include <linux/types.h> static __always_inline bool kuap_is_disabled(void); +static __always_inline void mtspr_uaccess_begin(int rn, unsigned long val); +static __always_inline void mtspr_uaccess_end(int rn, unsigned long val); #endif #ifdef CONFIG_PPC_BOOK3S_64 @@ -222,6 +224,16 @@ static __always_inline void prevent_current_write_to_user(void) prevent_user_access(KUAP_WRITE); } +static __always_inline void mtspr_uaccess_begin(int rn, unsigned long val) +{ + asm(ASM_UACCESS_BEGIN "mtspr %0, %1\n\t" : : "i"(rn), "r"(val) : "memory"); +} + +static __always_inline void mtspr_uaccess_end(int rn, unsigned long val) +{ + asm(ASM_UACCESS_END "mtspr %0, %1\n\t" : : "i"(rn), "r"(val) : "memory"); +} + #endif /* !__ASSEMBLY__ */ #endif /* _ASM_POWERPC_KUAP_H_ */ diff --git a/arch/powerpc/include/asm/nohash/32/kup-8xx.h b/arch/powerpc/include/asm/nohash/32/kup-8xx.h index 61067e4c8f22..9b59231d87c9 100644 --- a/arch/powerpc/include/asm/nohash/32/kup-8xx.h +++ b/arch/powerpc/include/asm/nohash/32/kup-8xx.h @@ -42,12 +42,12 @@ static __always_inline unsigned long __kuap_get_and_assert_locked(void) static __always_inline void __allow_user_access(void __user *to, const void __user *from, unsigned long size, unsigned long dir) { - mtspr(SPRN_MD_AP, MD_APG_INIT); + mtspr_uaccess_begin(SPRN_MD_AP, MD_APG_INIT); } static __always_inline void __prevent_user_access(unsigned long dir) { - mtspr(SPRN_MD_AP, MD_APG_KUAP); + mtspr_uaccess_end(SPRN_MD_AP, MD_APG_KUAP); } static __always_inline unsigned long __prevent_user_access_return(void) @@ -56,14 +56,14 @@ static __always_inline unsigned long __prevent_user_access_return(void) flags = mfspr(SPRN_MD_AP); - mtspr(SPRN_MD_AP, MD_APG_KUAP); + mtspr_uaccess_end(SPRN_MD_AP, MD_APG_KUAP); return flags; } static __always_inline void __restore_user_access(unsigned long flags) { - mtspr(SPRN_MD_AP, flags); + mtspr_uaccess_begin(SPRN_MD_AP, flags); } static __always_inline bool diff --git a/arch/powerpc/include/asm/nohash/kup-booke.h b/arch/powerpc/include/asm/nohash/kup-booke.h index 416f3e0897d5..2967501c434e 100644 --- a/arch/powerpc/include/asm/nohash/kup-booke.h +++ b/arch/powerpc/include/asm/nohash/kup-booke.h @@ -64,13 +64,13 @@ static __always_inline unsigned long __kuap_get_and_assert_locked(void) static __always_inline void __allow_user_access(void __user *to, const void __user *from, unsigned long size, unsigned long dir) { - mtspr(SPRN_PID, current->thread.pid); + mtspr_uaccess_begin(SPRN_PID, current->thread.pid); isync(); } static __always_inline void __prevent_user_access(unsigned long dir) { - mtspr(SPRN_PID, 0); + mtspr_uaccess_end(SPRN_PID, 0); isync(); } @@ -78,7 +78,7 @@ static __always_inline unsigned long __prevent_user_access_return(void) { unsigned long flags = mfspr(SPRN_PID); - mtspr(SPRN_PID, 0); + mtspr_uaccess_end(SPRN_PID, 0); isync(); return flags; @@ -87,7 +87,7 @@ static __always_inline unsigned long __prevent_user_access_return(void) static __always_inline void __restore_user_access(unsigned long flags) { if (flags) { - mtspr(SPRN_PID, current->thread.pid); + mtspr_uaccess_begin(SPRN_PID, current->thread.pid); isync(); } } diff --git a/arch/powerpc/kexec/core_32.c b/arch/powerpc/kexec/core_32.c index c95f96850c9e..6e955f32e7c3 100644 --- a/arch/powerpc/kexec/core_32.c +++ b/arch/powerpc/kexec/core_32.c @@ -17,7 +17,7 @@ typedef void (*relocate_new_kernel_t)( unsigned long indirection_page, unsigned long reboot_code_buffer, - unsigned long start_address) __noreturn; + unsigned long start_address); /* * This is a generic machine_kexec function suitable at least for @@ -61,6 +61,8 @@ void default_machine_kexec(struct kimage *image) /* now call it */ rnk = (relocate_new_kernel_t) reboot_code_buffer; (*rnk)(page_list, reboot_code_buffer_phys, image->start); + + unreachable(); /* For objtool */ } int machine_kexec_prepare(struct kimage *image) diff --git a/tools/objtool/arch/powerpc/decode.c b/tools/objtool/arch/powerpc/decode.c index 53b55690f320..2ed5241eb7be 100644 --- a/tools/objtool/arch/powerpc/decode.c +++ b/tools/objtool/arch/powerpc/decode.c @@ -43,24 +43,94 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec unsigned long offset, unsigned int maxlen, struct instruction *insn) { - unsigned int opcode; + unsigned int opcode, xop; + unsigned int rs, ra, rb, bo, bi, to, uimm, simm, lk, aa; enum insn_type typ; unsigned long imm; u32 ins; + if (file->elf->ehdr.e_flags & EF_PPC_RELOCATABLE_LIB) { + struct reloc *reloc; + + reloc = find_reloc_by_dest_range(file->elf, insn->sec, insn->offset, 4); + + if (reloc && reloc->type == R_PPC_REL32 && + !strncmp(reloc->sym->sec->name, ".got2", 5)) { + insn->type = INSN_OTHER; + insn->ignore = true; + insn->len = 4; + + return 0; + } + } + ins = bswap_if_needed(file->elf, *(u32 *)(sec->data->d_buf + offset)); opcode = ins >> 26; - typ = INSN_OTHER; - imm = 0; + xop = (ins >> 1) & 0x3ff; + rs = bo = to = (ins >> 21) & 0x1f; + ra = bi = (ins >> 16) & 0x1f; + rb = (ins >> 11) & 0x1f; + uimm = simm = (ins >> 0) & 0xffff; + aa = ins & 2; + lk = ins & 1; switch (opcode) { + case 3: + if (to == 31 && ra == 0 && simm == 0) /* twi 31, r0, 0 */ + typ = INSN_BUG; + else + typ = INSN_OTHER; + break; + case 16: /* bc[l][a] */ + if (lk) /* bcl[a] */ + typ = INSN_OTHER; + else /* bc[a] */ + typ = INSN_JUMP_CONDITIONAL; + + imm = ins & 0xfffc; + if (imm & 0x8000) + imm -= 0x10000; + insn->immediate = imm | aa; + break; case 18: /* b[l][a] */ - if ((ins & 3) == 1) /* bl */ + if (lk) /* bl[a] */ typ = INSN_CALL; + else /* b[a] */ + typ = INSN_JUMP_UNCONDITIONAL; imm = ins & 0x3fffffc; if (imm & 0x2000000) imm -= 0x4000000; + insn->immediate = imm | aa; + break; + case 19: + if (xop == 16 && bo == 20 && bi == 0) /* blr */ + typ = INSN_RETURN; + else if (xop == 16) /* bclr */ + typ = INSN_RETURN_CONDITIONAL; + else if (xop == 50) /* rfi */ + typ = INSN_JUMP_DYNAMIC; + else if (xop == 528 && bo == 20 && bi == 0 && !lk) /* bctr */ + typ = INSN_JUMP_DYNAMIC; + else if (xop == 528 && bo == 20 && bi == 0 && lk) /* bctrl */ + typ = INSN_CALL_DYNAMIC; + else + typ = INSN_OTHER; + break; + case 24: + if (rs == 0 && ra == 0 && uimm == 0) + typ = INSN_NOP; + else + typ = INSN_OTHER; + break; + case 31: + if (xop == 4 && to == 31 && ra == 0 && rb == 0) /* trap */ + typ = INSN_BUG; + else + typ = INSN_OTHER; + break; + default: + typ = INSN_OTHER; break; } @@ -70,13 +140,15 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec insn->len = 4; insn->type = typ; - insn->immediate = imm; return 0; } unsigned long arch_jump_destination(struct instruction *insn) { + if (insn->immediate & 2) + return insn->immediate & ~2; + return insn->offset + insn->immediate; } diff --git a/tools/objtool/arch/powerpc/special.c b/tools/objtool/arch/powerpc/special.c index 979b555b16ea..be37f4b455dc 100644 --- a/tools/objtool/arch/powerpc/special.c +++ b/tools/objtool/arch/powerpc/special.c @@ -15,5 +15,45 @@ bool arch_support_alt_relocation(struct special_alt *special_alt, struct reloc *arch_find_switch_table(struct objtool_file *file, struct instruction *insn, bool *is_rel) { - exit(-1); + struct reloc *text_reloc, *rodata_reloc; + struct section *table_sec; + unsigned long table_offset; + + /* look for a relocation which references .rodata */ + text_reloc = find_reloc_by_dest_range(file->elf, insn->sec, + insn->offset, insn->len); + if (!text_reloc || text_reloc->sym->type != STT_SECTION || + !text_reloc->sym->sec->rodata) + return NULL; + + table_offset = text_reloc->addend; + table_sec = text_reloc->sym->sec; + + /* + * Make sure the .rodata address isn't associated with a + * symbol. GCC jump tables are anonymous data. + * + * Also support C jump tables which are in the same format as + * switch jump tables. For objtool to recognize them, they + * need to be placed in the C_JUMP_TABLE_SECTION section. They + * have symbols associated with them. + */ + if (find_symbol_containing(table_sec, table_offset)) { + if (strcmp(table_sec->name, C_JUMP_TABLE_SECTION)) + return NULL; + *is_rel = false; + } else { + *is_rel = true; + } + + /* + * Each table entry has a rela associated with it. The rela + * should reference text in the same function as the original + * instruction. + */ + rodata_reloc = find_reloc_by_dest(file->elf, table_sec, table_offset); + if (!rodata_reloc) + return NULL; + + return rodata_reloc; } diff --git a/tools/objtool/check.c b/tools/objtool/check.c index f850ab892ad5..8ac5711a055f 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -218,6 +218,7 @@ static bool __dead_end_function(struct objtool_file *file, struct symbol *func, "kthread_exit", "kunit_try_catch_throw", "lbug_with_loc", + "longjmp", "machine_real_restart", "make_task_dead", "mpt_halt_firmware", @@ -230,7 +231,9 @@ static bool __dead_end_function(struct objtool_file *file, struct symbol *func, "sev_es_terminate", "snp_abort", "start_kernel", + "start_secondary_resume", "stop_this_cpu", + "unrecoverable_exception", "usercopy_abort", "x86_64_start_kernel", "x86_64_start_reservations", @@ -1335,6 +1338,8 @@ static const char *uaccess_safe_builtin[] = { "rep_stos_alternative", "rep_movs_alternative", "__copy_user_nocache", + "__copy_tofrom_user", + "__arch_clear_user", NULL };
In order to implement UACCESS validation, objtool support for powerpc needs to be enhanced to decode more instructions. It also requires implementation of switch tables finding. On PPC32 it is similar to x86, switch tables are anonymous in .rodata, the difference is that the value is relative to its index in the table. Then comes the UACCESS enabling/disabling instructions. On booke and 8xx it is done with a mtspr instruction. For 8xx that's in SPRN_MD_AP, for booke that's in SPRN_PID. Annotate those instructions. For book3s/32 that's a bit more complex and left aside for the moment. No work has been done for ASM files, they are not used for UACCESS so for the moment just tell objtool to ignore ASM files. For relocable code, the .got2 relocation preceding each global function needs to be marked as ignored because some versions of GCC do this: 120: R_PPC_REL32 .got2+0x7ff0 00000124 <tohex>: 124: 94 21 ff f0 stwu r1,-16(r1) 128: 7c 08 02 a6 mflr r0 12c: 42 9f 00 05 bcl 20,4*cr7+so,130 <tohex+0xc> 130: 39 00 00 00 li r8,0 134: 39 20 00 08 li r9,8 138: 93 c1 00 08 stw r30,8(r1) 13c: 7f c8 02 a6 mflr r30 140: 90 01 00 14 stw r0,20(r1) 144: 80 1e ff f0 lwz r0,-16(r30) 148: 7f c0 f2 14 add r30,r0,r30 14c: 81 5e 80 00 lwz r10,-32768(r30) 150: 80 fe 80 04 lwz r7,-32764(r30) While other versions do that: 00000120 <tohex>: 120: 94 21 ff f0 stwu r1,-16(r1) 124: 7c 08 02 a6 mflr r0 128: 42 9f 00 05 bcl 20,4*cr7+so,12c <tohex+0xc> 12c: 39 00 00 00 li r8,0 130: 39 20 00 08 li r9,8 134: 93 c1 00 08 stw r30,8(r1) 138: 7f c8 02 a6 mflr r30 13c: 3f de 00 00 addis r30,r30,0 13e: R_PPC_REL16_HA .got2+0x8012 140: 90 01 00 14 stw r0,20(r1) 144: 3b de 00 00 addi r30,r30,0 146: R_PPC_REL16_LO .got2+0x801a 148: 81 5e 80 00 lwz r10,-32768(r30) 14c: 80 fe 80 04 lwz r7,-32764(r30) Also declare longjmp() and start_secondary_resume() as global noreturn functions, and declare __copy_tofrom_user() and __arch_clear_user() as UACCESS safe. Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu> --- arch/powerpc/Kconfig | 2 + arch/powerpc/include/asm/kup.h | 12 +++ arch/powerpc/include/asm/nohash/32/kup-8xx.h | 8 +- arch/powerpc/include/asm/nohash/kup-booke.h | 8 +- arch/powerpc/kexec/core_32.c | 4 +- tools/objtool/arch/powerpc/decode.c | 82 ++++++++++++++++++-- tools/objtool/arch/powerpc/special.c | 42 +++++++++- tools/objtool/check.c | 5 ++ 8 files changed, 148 insertions(+), 15 deletions(-)