1 /* SPDX-License-Identifier: GPL-2.0 */ 1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef __LINUX_INSTRUMENTATION_H 2 #ifndef __LINUX_INSTRUMENTATION_H 3 #define __LINUX_INSTRUMENTATION_H 3 #define __LINUX_INSTRUMENTATION_H 4 4 5 #ifdef CONFIG_NOINSTR_VALIDATION !! 5 #if defined(CONFIG_DEBUG_ENTRY) && defined(CONFIG_STACK_VALIDATION) 6 << 7 #include <linux/stringify.h> << 8 6 9 /* Begin/end of an instrumentation safe region 7 /* Begin/end of an instrumentation safe region */ 10 #define __instrumentation_begin(c) ({ !! 8 #define instrumentation_begin() ({ \ 11 asm volatile(__stringify(c) ": nop\n\t !! 9 asm volatile("%c0: nop\n\t" \ 12 ".pushsection .discard.in 10 ".pushsection .discard.instr_begin\n\t" \ 13 ".long " __stringify(c) " !! 11 ".long %c0b - .\n\t" \ 14 ".popsection\n\t" : : "i" !! 12 ".popsection\n\t" : : "i" (__COUNTER__)); \ 15 }) 13 }) 16 #define instrumentation_begin() __instrumentat << 17 14 18 /* 15 /* 19 * Because instrumentation_{begin,end}() can n 16 * Because instrumentation_{begin,end}() can nest, objtool validation considers 20 * _begin() a +1 and _end() a -1 and computes 17 * _begin() a +1 and _end() a -1 and computes a sum over the instructions. 21 * When the value is greater than 0, we consid 18 * When the value is greater than 0, we consider instrumentation allowed. 22 * 19 * 23 * There is a problem with code like: 20 * There is a problem with code like: 24 * 21 * 25 * noinstr void foo() 22 * noinstr void foo() 26 * { 23 * { 27 * instrumentation_begin(); 24 * instrumentation_begin(); 28 * ... 25 * ... 29 * if (cond) { 26 * if (cond) { 30 * instrumentation_begin(); 27 * instrumentation_begin(); 31 * ... 28 * ... 32 * instrumentation_end(); 29 * instrumentation_end(); 33 * } 30 * } 34 * bar(); 31 * bar(); 35 * instrumentation_end(); 32 * instrumentation_end(); 36 * } 33 * } 37 * 34 * 38 * If instrumentation_end() would be an empty 35 * If instrumentation_end() would be an empty label, like all the other 39 * annotations, the inner _end(), which is at 36 * annotations, the inner _end(), which is at the end of a conditional block, 40 * would land on the instruction after the blo 37 * would land on the instruction after the block. 41 * 38 * 42 * If we then consider the sum of the !cond pa 39 * If we then consider the sum of the !cond path, we'll see that the call to 43 * bar() is with a 0-value, even though, we me 40 * bar() is with a 0-value, even though, we meant it to happen with a positive 44 * value. 41 * value. 45 * 42 * 46 * To avoid this, have _end() be a NOP instruc 43 * To avoid this, have _end() be a NOP instruction, this ensures it will be 47 * part of the condition block and does not es 44 * part of the condition block and does not escape. 48 */ 45 */ 49 #define __instrumentation_end(c) ({ !! 46 #define instrumentation_end() ({ \ 50 asm volatile(__stringify(c) ": nop\n\t !! 47 asm volatile("%c0: nop\n\t" \ 51 ".pushsection .discard.in 48 ".pushsection .discard.instr_end\n\t" \ 52 ".long " __stringify(c) " !! 49 ".long %c0b - .\n\t" \ 53 ".popsection\n\t" : : "i" !! 50 ".popsection\n\t" : : "i" (__COUNTER__)); \ 54 }) 51 }) 55 #define instrumentation_end() __instrumentatio !! 52 #else 56 #else /* !CONFIG_NOINSTR_VALIDATION */ << 57 # define instrumentation_begin() do { } 53 # define instrumentation_begin() do { } while(0) 58 # define instrumentation_end() do { } 54 # define instrumentation_end() do { } while(0) 59 #endif /* CONFIG_NOINSTR_VALIDATION */ !! 55 #endif 60 56 61 #endif /* __LINUX_INSTRUMENTATION_H */ 57 #endif /* __LINUX_INSTRUMENTATION_H */ 62 58
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.