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