From d8c34b949d8c9f61e099e00f22770e400adf2b76 Mon Sep 17 00:00:00 2001 From: Gideon Israel Dsouza Date: Sat, 31 Dec 2016 21:26:23 +0530 Subject: crypto: Replaced gcc specific attributes with macros from compiler.h Continuing from this commit: 52f5684c8e1e ("kernel: use macros from compiler.h instead of __attribute__((...))") I submitted 4 total patches. They are part of task I've taken up to increase compiler portability in the kernel. I've cleaned up the subsystems under /kernel /mm /block and /security, this patch targets /crypto. There is which provides macros for various gcc specific constructs. Eg: __weak for __attribute__((weak)). I've cleaned all instances of gcc specific attributes with the right macros for the crypto subsystem. I had to make one additional change into compiler-gcc.h for the case when one wants to use this: __attribute__((aligned) and not specify an alignment factor. From the gcc docs, this will result in the largest alignment for that data type on the target machine so I've named the macro __aligned_largest. Please advise if another name is more appropriate. Signed-off-by: Gideon Israel Dsouza Signed-off-by: Herbert Xu --- include/linux/compiler-gcc.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux/compiler-gcc.h') diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h index 0444b1336268..fddd1a5eb322 100644 --- a/include/linux/compiler-gcc.h +++ b/include/linux/compiler-gcc.h @@ -116,6 +116,7 @@ */ #define __pure __attribute__((pure)) #define __aligned(x) __attribute__((aligned(x))) +#define __aligned_largest __attribute__((aligned)) #define __printf(a, b) __attribute__((format(printf, a, b))) #define __scanf(a, b) __attribute__((format(scanf, a, b))) #define __attribute_const__ __attribute__((__const__)) -- cgit From d1091c7fa3d52ebce4dd3f15d04155b3469b2f90 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Tue, 21 Feb 2017 15:35:32 -0600 Subject: objtool: Improve detection of BUG() and other dead ends The BUG() macro's use of __builtin_unreachable() via the unreachable() macro tells gcc that the instruction is a dead end, and that it's safe to assume the current code path will not execute past the previous instruction. On x86, the BUG() macro is implemented with the 'ud2' instruction. When objtool's branch analysis sees that instruction, it knows the current code path has come to a dead end. Peter Zijlstra has been working on a patch to change the WARN macros to use 'ud2'. That patch will break objtool's assumption that 'ud2' is always a dead end. Generally it's best for objtool to avoid making those kinds of assumptions anyway. The more ignorant it is of kernel code internals, the better. So create a more generic way for objtool to detect dead ends by adding an annotation to the unreachable() macro. The annotation stores a pointer to the end of the unreachable code path in an '__unreachable' section. Objtool can read that section to find the dead ends. Tested-by: Peter Zijlstra (Intel) Signed-off-by: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/41a6d33971462ebd944a1c60ad4bf5be86c17b77.1487712920.git.jpoimboe@redhat.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/vmlinux.lds.S | 1 + include/linux/compiler-gcc.h | 13 ++++++++- tools/objtool/arch.h | 5 ++-- tools/objtool/arch/x86/decode.c | 3 --- tools/objtool/builtin-check.c | 60 ++++++++++++++++++++++++++++++++++++++--- 5 files changed, 71 insertions(+), 11 deletions(-) (limited to 'include/linux/compiler-gcc.h') diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index e79f15f108a8..ad0118fbce90 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S @@ -346,6 +346,7 @@ SECTIONS /DISCARD/ : { *(.eh_frame) *(__func_stack_frame_non_standard) + *(__unreachable) } } diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h index 0444b1336268..8ea159fc489d 100644 --- a/include/linux/compiler-gcc.h +++ b/include/linux/compiler-gcc.h @@ -195,6 +195,17 @@ #endif #endif +#ifdef CONFIG_STACK_VALIDATION +#define annotate_unreachable() ({ \ + asm("1:\t\n" \ + ".pushsection __unreachable, \"a\"\t\n" \ + ".long 1b\t\n" \ + ".popsection\t\n"); \ +}) +#else +#define annotate_unreachable() +#endif + /* * Mark a position in code as unreachable. This can be used to * suppress control flow warnings after asm blocks that transfer @@ -204,7 +215,7 @@ * this in the preprocessor, but we can live with this because they're * unreleased. Really, we need to have autoconf for the kernel. */ -#define unreachable() __builtin_unreachable() +#define unreachable() annotate_unreachable(); __builtin_unreachable() /* Mark a function definition as prohibited from being cloned. */ #define __noclone __attribute__((__noclone__, __optimize__("no-tracer"))) diff --git a/tools/objtool/arch.h b/tools/objtool/arch.h index f7350fcedc70..a59e061c0b4a 100644 --- a/tools/objtool/arch.h +++ b/tools/objtool/arch.h @@ -31,9 +31,8 @@ #define INSN_CALL_DYNAMIC 8 #define INSN_RETURN 9 #define INSN_CONTEXT_SWITCH 10 -#define INSN_BUG 11 -#define INSN_NOP 12 -#define INSN_OTHER 13 +#define INSN_NOP 11 +#define INSN_OTHER 12 #define INSN_LAST INSN_OTHER int arch_decode_instruction(struct elf *elf, struct section *sec, diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c index 039636ffb6c8..6ac99e3266eb 100644 --- a/tools/objtool/arch/x86/decode.c +++ b/tools/objtool/arch/x86/decode.c @@ -118,9 +118,6 @@ int arch_decode_instruction(struct elf *elf, struct section *sec, op2 == 0x35) /* sysenter, sysret */ *type = INSN_CONTEXT_SWITCH; - else if (op2 == 0x0b || op2 == 0xb9) - /* ud2 */ - *type = INSN_BUG; else if (op2 == 0x0d || op2 == 0x1f) /* nopl/nopw */ *type = INSN_NOP; diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c index e8a1f699058a..5fc52ee3264c 100644 --- a/tools/objtool/builtin-check.c +++ b/tools/objtool/builtin-check.c @@ -51,7 +51,7 @@ struct instruction { unsigned int len, state; unsigned char type; unsigned long immediate; - bool alt_group, visited; + bool alt_group, visited, dead_end; struct symbol *call_dest; struct instruction *jump_dest; struct list_head alts; @@ -329,6 +329,54 @@ static int decode_instructions(struct objtool_file *file) return 0; } +/* + * Find all uses of the unreachable() macro, which are code path dead ends. + */ +static int add_dead_ends(struct objtool_file *file) +{ + struct section *sec; + struct rela *rela; + struct instruction *insn; + bool found; + + sec = find_section_by_name(file->elf, ".rela__unreachable"); + if (!sec) + return 0; + + list_for_each_entry(rela, &sec->rela_list, list) { + if (rela->sym->type != STT_SECTION) { + WARN("unexpected relocation symbol type in .rela__unreachable"); + return -1; + } + insn = find_insn(file, rela->sym->sec, rela->addend); + if (insn) + insn = list_prev_entry(insn, list); + else if (rela->addend == rela->sym->sec->len) { + found = false; + list_for_each_entry_reverse(insn, &file->insn_list, list) { + if (insn->sec == rela->sym->sec) { + found = true; + break; + } + } + + if (!found) { + WARN("can't find unreachable insn at %s+0x%x", + rela->sym->sec->name, rela->addend); + return -1; + } + } else { + WARN("can't find unreachable insn at %s+0x%x", + rela->sym->sec->name, rela->addend); + return -1; + } + + insn->dead_end = true; + } + + return 0; +} + /* * Warnings shouldn't be reported for ignored functions. */ @@ -843,6 +891,10 @@ static int decode_sections(struct objtool_file *file) if (ret) return ret; + ret = add_dead_ends(file); + if (ret) + return ret; + add_ignores(file); ret = add_jump_destinations(file); @@ -1037,13 +1089,13 @@ static int validate_branch(struct objtool_file *file, return 0; - case INSN_BUG: - return 0; - default: break; } + if (insn->dead_end) + return 0; + insn = next_insn_same_sec(file, insn); if (!insn) { WARN("%s: unexpected end of section", sec->name); -- cgit From a3f0825e7e37d99a02a8a1b1599687667ee50d04 Mon Sep 17 00:00:00 2001 From: Gideon Israel Dsouza Date: Fri, 24 Feb 2017 15:00:32 -0800 Subject: compiler-gcc.h: add a new macro to wrap gcc attribute Add __mode(x) into compiler-gcc.h as part of a cleanup task I've taken up, to replace gcc specific attributes with macros. The next patch is a cleanup of the m68k subsystem and it requires a new macro to wrap __attribute__ ((mode (...))) Link: http://lkml.kernel.org/r/1485540901-1988-2-git-send-email-gidisrael@gmail.com Signed-off-by: Gideon Israel Dsouza Cc: Greg Ungerer Cc: Geert Uytterhoeven Cc: Paul Gortmaker Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/compiler-gcc.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux/compiler-gcc.h') diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h index fddd1a5eb322..811f7a915658 100644 --- a/include/linux/compiler-gcc.h +++ b/include/linux/compiler-gcc.h @@ -122,6 +122,7 @@ #define __attribute_const__ __attribute__((__const__)) #define __maybe_unused __attribute__((unused)) #define __always_unused __attribute__((unused)) +#define __mode(x) __attribute__((mode(x))) /* gcc version specific checks */ -- cgit From 3d1e236022cc1426b0834565995ddee2ca231cee Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Fri, 24 Feb 2017 22:31:02 -0600 Subject: objtool: Prevent GCC from merging annotate_unreachable() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 0-day bot reported some new objtool warnings which were caused by the new annotate_unreachable() macro: fs/afs/flock.o: warning: objtool: afs_do_unlk()+0x0: duplicate frame pointer save fs/afs/flock.o: warning: objtool: afs_do_unlk()+0x0: frame pointer state mismatch fs/btrfs/delayed-inode.o: warning: objtool: btrfs_delete_delayed_dir_index()+0x0: duplicate frame pointer save fs/btrfs/delayed-inode.o: warning: objtool: btrfs_delete_delayed_dir_index()+0x0: frame pointer state mismatch fs/dlm/lock.o: warning: objtool: _grant_lock()+0x0: duplicate frame pointer save fs/dlm/lock.o: warning: objtool: _grant_lock()+0x0: frame pointer state mismatch fs/ocfs2/alloc.o: warning: objtool: ocfs2_mv_path()+0x0: duplicate frame pointer save fs/ocfs2/alloc.o: warning: objtool: ocfs2_mv_path()+0x0: frame pointer state mismatch It turns out that, for older versions of GCC, if a function has multiple BUG() incantations, GCC will sometimes merge the corresponding annotate_unreachable() inline asm statements into a single block. That has the undesirable effect of removing one of the entries in the __unreachable section, confusing objtool greatly. A workaround for this issue is to ensure that each instance of the inline asm statement uses a different label, so that GCC sees the statements are unique and leaves them alone. The inline asm ‘%=’ token could be used for that, but unfortunately older versions of GCC don't support it. So I implemented a poor man's version of it with the __LINE__ macro. Reported-by: kbuild test robot Signed-off-by: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Fixes: d1091c7fa3d5 ("objtool: Improve detection of BUG() and other dead ends") Link: http://lkml.kernel.org/r/0c14b00baf9f68d1b0221ddb6c88b925181c8be8.1487997036.git.jpoimboe@redhat.com Signed-off-by: Ingo Molnar --- include/linux/compiler-gcc.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include/linux/compiler-gcc.h') diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h index 8ea159fc489d..de471346b365 100644 --- a/include/linux/compiler-gcc.h +++ b/include/linux/compiler-gcc.h @@ -197,10 +197,10 @@ #ifdef CONFIG_STACK_VALIDATION #define annotate_unreachable() ({ \ - asm("1:\t\n" \ + asm("%c0:\t\n" \ ".pushsection __unreachable, \"a\"\t\n" \ - ".long 1b\t\n" \ - ".popsection\t\n"); \ + ".long %c0b\t\n" \ + ".popsection\t\n" : : "i" (__LINE__)); \ }) #else #define annotate_unreachable() -- cgit From 4e4636cf981b5b629fbfb78aa9f232e015f7d521 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Mon, 27 Feb 2017 22:21:16 -0600 Subject: objtool: Enclose contents of unreachable() macro in a block Guenter Roeck reported a boot failure in mips64. It was bisected to the following commit: d1091c7fa3d5 ("objtool: Improve detection of BUG() and other dead ends") The unreachable() macro was formerly only composed of a single statement. The above commit added a second statement, but neglected to enclose the statements in a block. Suggested-by: Guenter Roeck Reported-by: Guenter Roeck Signed-off-by: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Fixes: d1091c7fa3d5 ("objtool: Improve detection of BUG() and other dead ends") Link: http://lkml.kernel.org/r/20170228042116.glmwmwiohcix7o4a@treble Signed-off-by: Ingo Molnar --- include/linux/compiler-gcc.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include/linux/compiler-gcc.h') diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h index de471346b365..f457b520ead6 100644 --- a/include/linux/compiler-gcc.h +++ b/include/linux/compiler-gcc.h @@ -215,7 +215,8 @@ * this in the preprocessor, but we can live with this because they're * unreleased. Really, we need to have autoconf for the kernel. */ -#define unreachable() annotate_unreachable(); __builtin_unreachable() +#define unreachable() \ + do { annotate_unreachable(); __builtin_unreachable(); } while (0) /* Mark a function definition as prohibited from being cloned. */ #define __noclone __attribute__((__noclone__, __optimize__("no-tracer"))) -- cgit From 55149d06534ae2a7ba5f7a078353deb89b3fe891 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Wed, 1 Mar 2017 00:05:04 -0600 Subject: objtool, compiler.h: Fix __unreachable section relocation size Linus reported the following commit broke module loading on his laptop: d1091c7fa3d5 ("objtool: Improve detection of BUG() and other dead ends") It showed errors like the following: module: overflow in relocation type 10 val ffffffffc02afc81 module: 'nvme' likely not compiled with -mcmodel=kernel The problem is that the __unreachable section addresses are stored using the '.long' asm directive, which isn't big enough for .text section kernel addresses. Use relative addresses instead: ".long %c0b - .\t\n" Suggested-by: Linus Torvalds Reported-by: Linus Torvalds Signed-off-by: Josh Poimboeuf Cc: Peter Zijlstra Cc: Peter Zijlstra Cc: Thomas Gleixner Fixes: d1091c7fa3d5 ("objtool: Improve detection of BUG() and other dead ends") Link: http://lkml.kernel.org/r/20170301060504.oltm3iws6fmubnom@treble Signed-off-by: Ingo Molnar --- include/linux/compiler-gcc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux/compiler-gcc.h') diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h index 76e28c229805..b6bb9019d87f 100644 --- a/include/linux/compiler-gcc.h +++ b/include/linux/compiler-gcc.h @@ -201,7 +201,7 @@ #define annotate_unreachable() ({ \ asm("%c0:\t\n" \ ".pushsection __unreachable, \"a\"\t\n" \ - ".long %c0b\t\n" \ + ".long %c0b - .\t\n" \ ".popsection\t\n" : : "i" (__LINE__)); \ }) #else -- cgit From e390f9a9689a42f477a6073e2e7df530a4c1b740 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Wed, 1 Mar 2017 12:04:44 -0600 Subject: objtool, modules: Discard objtool annotation sections for modules The '__unreachable' and '__func_stack_frame_non_standard' sections are only used at compile time. They're discarded for vmlinux but they should also be discarded for modules. Since this is a recurring pattern, prefix the section names with ".discard.". It's a nice convention and vmlinux.lds.h already discards such sections. Also remove the 'a' (allocatable) flag from the __unreachable section since it doesn't make sense for a discarded section. Suggested-by: Linus Torvalds Signed-off-by: Josh Poimboeuf Cc: Jessica Yu Cc: Peter Zijlstra Cc: Thomas Gleixner Fixes: d1091c7fa3d5 ("objtool: Improve detection of BUG() and other dead ends") Link: http://lkml.kernel.org/r/20170301180444.lhd53c5tibc4ns77@treble Signed-off-by: Ingo Molnar --- arch/x86/kernel/vmlinux.lds.S | 2 -- include/linux/compiler-gcc.h | 2 +- include/linux/frame.h | 2 +- scripts/mod/modpost.c | 1 + scripts/module-common.lds | 5 ++++- tools/objtool/builtin-check.c | 6 +++--- 6 files changed, 10 insertions(+), 8 deletions(-) (limited to 'include/linux/compiler-gcc.h') diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index ad0118fbce90..c74ae9ce8dc4 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S @@ -345,8 +345,6 @@ SECTIONS DISCARDS /DISCARD/ : { *(.eh_frame) - *(__func_stack_frame_non_standard) - *(__unreachable) } } diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h index b6bb9019d87f..0efef9cf014f 100644 --- a/include/linux/compiler-gcc.h +++ b/include/linux/compiler-gcc.h @@ -200,7 +200,7 @@ #ifdef CONFIG_STACK_VALIDATION #define annotate_unreachable() ({ \ asm("%c0:\t\n" \ - ".pushsection __unreachable, \"a\"\t\n" \ + ".pushsection .discard.unreachable\t\n" \ ".long %c0b - .\t\n" \ ".popsection\t\n" : : "i" (__LINE__)); \ }) diff --git a/include/linux/frame.h b/include/linux/frame.h index e6baaba3f1ae..d772c61c31da 100644 --- a/include/linux/frame.h +++ b/include/linux/frame.h @@ -11,7 +11,7 @@ * For more information, see tools/objtool/Documentation/stack-validation.txt. */ #define STACK_FRAME_NON_STANDARD(func) \ - static void __used __section(__func_stack_frame_non_standard) \ + static void __used __section(.discard.func_stack_frame_non_standard) \ *__func_stack_frame_non_standard_##func = func #else /* !CONFIG_STACK_VALIDATION */ diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 4dedd0d3d3a7..30d752a4a6a6 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -854,6 +854,7 @@ static const char *const section_white_list[] = ".cmem*", /* EZchip */ ".fmt_slot*", /* EZchip */ ".gnu.lto*", + ".discard.*", NULL }; diff --git a/scripts/module-common.lds b/scripts/module-common.lds index 73a2c7da0e55..cf7e52e4781b 100644 --- a/scripts/module-common.lds +++ b/scripts/module-common.lds @@ -4,7 +4,10 @@ * combine them automatically. */ SECTIONS { - /DISCARD/ : { *(.discard) } + /DISCARD/ : { + *(.discard) + *(.discard.*) + } __ksymtab 0 : { *(SORT(___ksymtab+*)) } __ksymtab_gpl 0 : { *(SORT(___ksymtab_gpl+*)) } diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c index 5fc52ee3264c..4cfdbb5b6967 100644 --- a/tools/objtool/builtin-check.c +++ b/tools/objtool/builtin-check.c @@ -339,13 +339,13 @@ static int add_dead_ends(struct objtool_file *file) struct instruction *insn; bool found; - sec = find_section_by_name(file->elf, ".rela__unreachable"); + sec = find_section_by_name(file->elf, ".rela.discard.unreachable"); if (!sec) return 0; list_for_each_entry(rela, &sec->rela_list, list) { if (rela->sym->type != STT_SECTION) { - WARN("unexpected relocation symbol type in .rela__unreachable"); + WARN("unexpected relocation symbol type in %s", sec->name); return -1; } insn = find_insn(file, rela->sym->sec, rela->addend); @@ -1272,7 +1272,7 @@ int cmd_check(int argc, const char **argv) INIT_LIST_HEAD(&file.insn_list); hash_init(file.insn_hash); - file.whitelist = find_section_by_name(file.elf, "__func_stack_frame_non_standard"); + file.whitelist = find_section_by_name(file.elf, ".discard.func_stack_frame_non_standard"); file.rodata = find_section_by_name(file.elf, ".rodata"); file.ignore_unreachables = false; file.c_file = find_section_by_name(file.elf, ".comment"); -- cgit