hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/arch/x86/kernel/module.c
....@@ -1,19 +1,7 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /* Kernel module help for x86.
23 Copyright (C) 2001 Rusty Russell.
34
4
- This program is free software; you can redistribute it and/or modify
5
- it under the terms of the GNU General Public License as published by
6
- the Free Software Foundation; either version 2 of the License, or
7
- (at your option) any later version.
8
-
9
- This program is distributed in the hope that it will be useful,
10
- but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- GNU General Public License for more details.
13
-
14
- You should have received a copy of the GNU General Public License
15
- along with this program; if not, write to the Free Software
16
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
175 */
186
197 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
....@@ -30,10 +18,10 @@
3018 #include <linux/gfp.h>
3119 #include <linux/jump_label.h>
3220 #include <linux/random.h>
21
+#include <linux/memory.h>
3322
3423 #include <asm/text-patching.h>
3524 #include <asm/page.h>
36
-#include <asm/pgtable.h>
3725 #include <asm/setup.h>
3826 #include <asm/unwind.h>
3927
....@@ -139,11 +127,12 @@
139127 return 0;
140128 }
141129 #else /*X86_64*/
142
-int apply_relocate_add(Elf64_Shdr *sechdrs,
130
+static int __apply_relocate_add(Elf64_Shdr *sechdrs,
143131 const char *strtab,
144132 unsigned int symindex,
145133 unsigned int relsec,
146
- struct module *me)
134
+ struct module *me,
135
+ void *(*write)(void *dest, const void *src, size_t len))
147136 {
148137 unsigned int i;
149138 Elf64_Rela *rel = (void *)sechdrs[relsec].sh_addr;
....@@ -175,19 +164,19 @@
175164 case R_X86_64_64:
176165 if (*(u64 *)loc != 0)
177166 goto invalid_relocation;
178
- *(u64 *)loc = val;
167
+ write(loc, &val, 8);
179168 break;
180169 case R_X86_64_32:
181170 if (*(u32 *)loc != 0)
182171 goto invalid_relocation;
183
- *(u32 *)loc = val;
172
+ write(loc, &val, 4);
184173 if (val != *(u32 *)loc)
185174 goto overflow;
186175 break;
187176 case R_X86_64_32S:
188177 if (*(s32 *)loc != 0)
189178 goto invalid_relocation;
190
- *(s32 *)loc = val;
179
+ write(loc, &val, 4);
191180 if ((s64)val != *(s32 *)loc)
192181 goto overflow;
193182 break;
....@@ -196,11 +185,17 @@
196185 if (*(u32 *)loc != 0)
197186 goto invalid_relocation;
198187 val -= (u64)loc;
199
- *(u32 *)loc = val;
188
+ write(loc, &val, 4);
200189 #if 0
201190 if ((s64)val != *(s32 *)loc)
202191 goto overflow;
203192 #endif
193
+ break;
194
+ case R_X86_64_PC64:
195
+ if (*(u64 *)loc != 0)
196
+ goto invalid_relocation;
197
+ val -= (u64)loc;
198
+ write(loc, &val, 8);
204199 break;
205200 case R_X86_64_8:
206201 if (!strncmp(strtab + sym->st_name, "__typeid__", 10))
....@@ -226,6 +221,33 @@
226221 me->name);
227222 return -ENOEXEC;
228223 }
224
+
225
+int apply_relocate_add(Elf64_Shdr *sechdrs,
226
+ const char *strtab,
227
+ unsigned int symindex,
228
+ unsigned int relsec,
229
+ struct module *me)
230
+{
231
+ int ret;
232
+ bool early = me->state == MODULE_STATE_UNFORMED;
233
+ void *(*write)(void *, const void *, size_t) = memcpy;
234
+
235
+ if (!early) {
236
+ write = text_poke;
237
+ mutex_lock(&text_mutex);
238
+ }
239
+
240
+ ret = __apply_relocate_add(sechdrs, strtab, symindex, relsec, me,
241
+ write);
242
+
243
+ if (!early) {
244
+ text_poke_sync();
245
+ mutex_unlock(&text_mutex);
246
+ }
247
+
248
+ return ret;
249
+}
250
+
229251 #endif
230252
231253 int module_finalize(const Elf_Ehdr *hdr,
....@@ -233,7 +255,8 @@
233255 struct module *me)
234256 {
235257 const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL,
236
- *para = NULL, *orc = NULL, *orc_ip = NULL;
258
+ *para = NULL, *orc = NULL, *orc_ip = NULL,
259
+ *retpolines = NULL, *returns = NULL;
237260 char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
238261
239262 for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
....@@ -249,8 +272,20 @@
249272 orc = s;
250273 if (!strcmp(".orc_unwind_ip", secstrings + s->sh_name))
251274 orc_ip = s;
275
+ if (!strcmp(".retpoline_sites", secstrings + s->sh_name))
276
+ retpolines = s;
277
+ if (!strcmp(".return_sites", secstrings + s->sh_name))
278
+ returns = s;
252279 }
253280
281
+ if (retpolines) {
282
+ void *rseg = (void *)retpolines->sh_addr;
283
+ apply_retpolines(rseg, rseg + retpolines->sh_size);
284
+ }
285
+ if (returns) {
286
+ void *rseg = (void *)returns->sh_addr;
287
+ apply_returns(rseg, rseg + returns->sh_size);
288
+ }
254289 if (alt) {
255290 /* patch .altinstructions */
256291 void *aseg = (void *)alt->sh_addr;