projects/linux·blob 5b6dca02 · refs

76 lines · 2.1 KiB

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
35static const char __modinfo[]
36 __attribute__((section(".modinfo"), used, aligned(1))) = "\0name=" MODNAME;
37
38#ifdef STATIC_KEY
39static long KEY_NAME;
40#else
41long KEY_NAME;
42#endif
43
44int 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;
67l_yes:
68 r += 2;
69out:
70#endif
71#ifdef PATCHED
72 return r + 100;
73#else
74 return r;
75#endif
76}