1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Instruction operands whose change must move a function's checksum even
4 * though the instruction bytes themselves do not.
5 *
6 * checksum_update_insn() hashes the raw bytes and then, when the instruction
7 * carries a relocation, what that relocation refers to: a string section
8 * contributes the string's contents, anything else the target symbol's name
9 * and the adjusted addend. A reference to a static arrives as a section
10 * symbol and has to be resolved back to the object first.
11 *
12 * The bytes are identical in every case below -- a rel32 operand is zero in
13 * the object and supplied by the relocation -- so a checksum that stopped at
14 * the bytes would call all of these unchanged.
15 *
16 * Each variant applies to the patched build only:
17 *
18 * WHICH_CALL calls a different function
19 * STR_CONTENT passes a literal whose text was edited
20 * WHICH_SLOT reads a different index of a global array: addend only
21 * WHICH_PRIV the same, for a static, reached through its section symbol
22 */
23
24 static const char __modinfo[]
25 __attribute__((section(".modinfo"), used, aligned(1))) = "\0name=vmlinux";
26
27 int callee_a(int x);
28 int callee_b(int x);
29 int sink(const char *s);
30
31 int slots[4];
32
33 /*
34 * A file-local array, plus a writer the compiler cannot see through. Without
35 * one it can prove the array is never written, folds every read to zero, and
36 * emits no relocation at all -- so the reference this is here to exercise does
37 * not exist.
38 */
39 static int priv_slots[4];
40
41 void set_priv(int i, int v);
set_priv(int i,int v)42 void set_priv(int i, int v)
43 {
44 priv_slots[i] = v;
45 }
46
47 #if defined(PATCHED) && defined(STR_CONTENT)
48 #define MESSAGE "edited"
49 #else
50 #define MESSAGE "original"
51 #endif
52
target(int x)53 int target(int x)
54 {
55 int r;
56
57 #if defined(PATCHED) && defined(WHICH_CALL)
58 r = callee_b(x);
59 #else
60 r = callee_a(x);
61 #endif
62
63 r += sink(MESSAGE);
64
65 #if defined(PATCHED) && defined(WHICH_SLOT)
66 r += slots[2];
67 #else
68 r += slots[1];
69 #endif
70
71 #if defined(PATCHED) && defined(WHICH_PRIV)
72 r += priv_slots[3];
73 #else
74 r += priv_slots[1];
75 #endif
76
77 return r;
78 }
79