1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Static branch in a patched function. The jump table entry is written out by 4 * hand, mirroring JUMP_TABLE_ENTRY(), so the fixture builds without kernel 5 * headers. The key is an STT_OBJECT; anything else is ignored by 6 * validate_special_section_klp_reloc(). 7 * 8 * MODNAME selects whether the key is taken to belong to vmlinux or a module. 9 * 10 * NEW_KEY puts the whole static branch behind PATCHED, so the patch introduces 11 * one where the original had none -- a different question from patching code 12 * that already has a key, because the __jump_table entry itself is new. 13 * 14 * KEY_NAME renames the key. Two names are special to 15 * validate_special_section_klp_reloc(): a __tracepoint_* key and the 16 * __UNIQUE_ID_ddebug_* one pr_debug() generates are both unsupported in a 17 * module, but are disabled with a warning rather than rejected, because the 18 * kernel is full of them and refusing outright would make ordinary functions 19 * unpatchable. 20 * 21 * STATIC_KEY makes the key file-local. That changes the shape of the 22 * relocation rather than the meaning of the code: a reference to a static lands 23 * on the section symbol plus an addend, so the key has to be resolved from the 24 * section before it can be recognised as a key at all. 25 */ 26 27 #ifndef MODNAME 28 #define MODNAME "vmlinux" 29 #endif 30 31 #ifndef KEY_NAME 32 #define KEY_NAME klp_test_key 33 #endif 34 35 static const char __modinfo[] 36 __attribute__((section(".modinfo"), used, aligned(1))) = "\0name=" MODNAME; 37 38 #ifdef STATIC_KEY 39 static long KEY_NAME; 40 #else 41 long KEY_NAME; 42 #endif 43 44 int target(int x) 45 { 46 int r = x; 47 48 #if defined(NEW_KEY) && !defined(PATCHED) 49 /* The original has no static branch at all. */ 50 return r + 1; 51 #else 52 asm goto( 53 "1: nop\n\t" 54 ".pushsection __jump_table, \"aw\"\n\t" 55 ".balign 8\n\t" 56 "912:\n\t" 57 ".pushsection .discard.annotate_data, \"M\", @progbits, 8\n\t" 58 ".long 912b - ., 1\n\t" 59 ".popsection\n\t" 60 ".long 1b - ., %l[l_yes] - .\n\t" 61 ".quad %c0 - .\n\t" 62 ".popsection\n\t" 63 : : "i" (&KEY_NAME) : : l_yes); 64 65 r += 1; 66 goto out; 67 l_yes: 68 r += 2; 69 out: 70 #endif 71 #ifdef PATCHED 72 return r + 100; 73 #else 74 return r; 75 #endif 76 } 77