projects/linux·blob master · refs

177 lines · 4.3 KiB

1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Read the intermediate KLP reloc/symbol representations created by klp diff
4 * and convert them to the proper format required by livepatch. This needs to
5 * run last to avoid linker wreckage. Linkers don't tend to handle the "two
6 * rela sections for a single base section" case very well, nor do they like
7 * SHN_LIVEPATCH.
8 *
9 * This is the final tool in the livepatch module generation pipeline:
10 *
11 * kernel builds -> objtool klp diff -> module link -> objtool klp post-link
12 */
13
14#include <fcntl.h>
15#include <gelf.h>
16#include <objtool/objtool.h>
17#include <objtool/warn.h>
18#include <objtool/klp.h>
19#include <objtool/util.h>
20#include <linux/livepatch_external.h>
21
22static int fix_klp_reloc_sec(struct elf *elf, struct section *symtab,
23 struct section *klp_relocs)
24{
25 /* section format: __klp_relocs.sec_objname */
26 const char *sec_objname = klp_relocs->name + strlen(KLP_RELOCS_SEC ".");
27
28 for (int i = 0; i < sec_size(klp_relocs) / sizeof(struct klp_reloc); i++) {
29 struct klp_reloc *klp_reloc;
30 unsigned long klp_reloc_off;
31 struct section *sec, *tmp, *klp_rsec;
32 unsigned long offset;
33 struct reloc *reloc;
34 char rsec_name[SEC_NAME_LEN];
35 u64 addend;
36 struct symbol *sym, *klp_sym;
37
38 klp_reloc_off = i * sizeof(*klp_reloc);
39 klp_reloc = klp_relocs->data->d_buf + klp_reloc_off;
40
41 /*
42 * Read __klp_relocs[i]:
43 */
44
45 /* klp_reloc.sec_offset */
46 reloc = find_reloc_by_dest(elf, klp_relocs,
47 klp_reloc_off + offsetof(struct klp_reloc, offset));
48 if (!reloc) {
49 ERROR("malformed %s section", klp_relocs->name);
50 return -1;
51 }
52
53 sec = reloc->sym->sec;
54 offset = reloc_addend(reloc);
55
56 /* klp_reloc.sym */
57 reloc = find_reloc_by_dest(elf, klp_relocs,
58 klp_reloc_off + offsetof(struct klp_reloc, sym));
59 if (!reloc) {
60 ERROR("malformed %s section", klp_relocs->name);
61 return -1;
62 }
63
64 klp_sym = reloc->sym;
65 addend = reloc_addend(reloc);
66
67 /*
68 * Create the KLP rela:
69 */
70
71 /* section format: .klp.rela.sec_objname.section_name */
72 if (snprintf_check(rsec_name, SEC_NAME_LEN,
73 KLP_RELOC_SEC_PREFIX "%s.%s",
74 sec_objname, sec->name))
75 return -1;
76
77 klp_rsec = find_section_by_name(elf, rsec_name);
78 if (!klp_rsec) {
79 klp_rsec = elf_create_section(elf, rsec_name, 0,
80 elf_rela_size(elf),
81 SHT_RELA, elf_addr_size(elf),
82 SHF_ALLOC | SHF_INFO_LINK | SHF_RELA_LIVEPATCH);
83 if (!klp_rsec)
84 return -1;
85
86 klp_rsec->sh.sh_link = symtab->idx;
87 klp_rsec->sh.sh_info = sec->idx;
88 klp_rsec->base = sec;
89 }
90
91 tmp = sec->rsec;
92 sec->rsec = klp_rsec;
93 if (!elf_create_reloc(elf, sec, offset, klp_sym, addend, klp_reloc->type))
94 return -1;
95 sec->rsec = tmp;
96
97 /*
98 * Fix up the corresponding KLP symbol:
99 */
100
101 klp_sym->sym.st_shndx = SHN_LIVEPATCH;
102 if (!gelf_update_sym(symtab->data, klp_sym->idx, &klp_sym->sym)) {
103 ERROR_ELF("gelf_update_sym");
104 return -1;
105 }
106
107 /*
108 * Disable the original non-KLP reloc by converting it to R_*_NONE:
109 */
110
111 reloc = find_reloc_by_dest(elf, sec, offset);
112 sym = reloc->sym;
113 sym->sym.st_shndx = SHN_LIVEPATCH;
114 set_reloc_type(elf, reloc, 0);
115 if (!gelf_update_sym(symtab->data, sym->idx, &sym->sym)) {
116 ERROR_ELF("gelf_update_sym");
117 return -1;
118 }
119 }
120
121 return 0;
122}
123
124static int fix_klp_relocs(struct elf *elf)
125{
126 struct section *symtab, *sec;
127
128 symtab = find_section_by_name(elf, ".symtab");
129 if (!symtab) {
130 ERROR("missing .symtab");
131 return -1;
132 }
133
134 for_each_sec(elf, sec) {
135 if (strncmp(sec->name, KLP_RELOCS_SEC ".",
136 strlen(KLP_RELOCS_SEC ".")))
137 continue;
138
139 if (fix_klp_reloc_sec(elf, symtab, sec))
140 return -1;
141 }
142
143 return 0;
144}
145
146/*
147 * This runs on the livepatch module after all other linking has been done. It
148 * converts the intermediate __klp_relocs.* sections into proper KLP relocs to
149 * be processed by livepatch. This needs to run last to avoid linker wreckage.
150 * Linkers don't tend to handle the "two rela sections for a single base
151 * section" case very well, nor do they appreciate SHN_LIVEPATCH.
152 */
153int cmd_klp_post_link(int argc, const char **argv)
154{
155 struct elf *elf;
156
157 argc--;
158 argv++;
159
160 if (argc != 1) {
161 fprintf(stderr, "%d\n", argc);
162 fprintf(stderr, "usage: objtool link <file.ko>\n");
163 return -1;
164 }
165
166 elf = elf_open_read(argv[0], O_RDWR);
167 if (!elf)
168 return -1;
169
170 if (fix_klp_relocs(elf))
171 return -1;
172
173 if (elf_write(elf))
174 return -1;
175
176 return elf_close(elf);
177}