Blame view

kernel/kexec_file.c 33.3 KB
40b0b3f8f   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
a43cac0d9   Dave Young   kexec: split kexe...
2
3
4
5
6
7
  /*
   * kexec: kexec_file_load system call
   *
   * Copyright (C) 2014 Red Hat Inc.
   * Authors:
   *      Vivek Goyal <vgoyal@redhat.com>
a43cac0d9   Dave Young   kexec: split kexe...
8
   */
de90a6bca   Minfei Huang   kexec: use file n...
9
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
a43cac0d9   Dave Young   kexec: split kexe...
10
11
12
13
14
  #include <linux/capability.h>
  #include <linux/mm.h>
  #include <linux/file.h>
  #include <linux/slab.h>
  #include <linux/kexec.h>
735c2f90e   AKASHI Takahiro   powerpc, kexec_fi...
15
  #include <linux/memblock.h>
a43cac0d9   Dave Young   kexec: split kexe...
16
17
  #include <linux/mutex.h>
  #include <linux/list.h>
b804defe4   Mimi Zohar   kexec: replace ca...
18
  #include <linux/fs.h>
7b8589cc2   Mimi Zohar   ima: on soft rebo...
19
  #include <linux/ima.h>
a43cac0d9   Dave Young   kexec: split kexe...
20
21
  #include <crypto/hash.h>
  #include <crypto/sha.h>
babac4a84   AKASHI Takahiro   kexec_file, x86: ...
22
23
24
  #include <linux/elf.h>
  #include <linux/elfcore.h>
  #include <linux/kernel.h>
b89999d00   Scott Branden   fs/kernel_read_fi...
25
  #include <linux/kernel_read_file.h>
a43cac0d9   Dave Young   kexec: split kexe...
26
27
28
  #include <linux/syscalls.h>
  #include <linux/vmalloc.h>
  #include "kexec_internal.h"
a43cac0d9   Dave Young   kexec: split kexe...
29
  static int kexec_calculate_store_digests(struct kimage *image);
9ec4ecef0   AKASHI Takahiro   kexec_file,x86,po...
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
  /*
   * Currently this is the only default function that is exported as some
   * architectures need it to do additional handlings.
   * In the future, other default functions may be exported too if required.
   */
  int kexec_image_probe_default(struct kimage *image, void *buf,
  			      unsigned long buf_len)
  {
  	const struct kexec_file_ops * const *fops;
  	int ret = -ENOEXEC;
  
  	for (fops = &kexec_file_loaders[0]; *fops && (*fops)->probe; ++fops) {
  		ret = (*fops)->probe(buf, buf_len);
  		if (!ret) {
  			image->fops = *fops;
  			return ret;
  		}
  	}
  
  	return ret;
  }
a43cac0d9   Dave Young   kexec: split kexe...
51
52
53
54
  /* Architectures can provide this probe function */
  int __weak arch_kexec_kernel_image_probe(struct kimage *image, void *buf,
  					 unsigned long buf_len)
  {
9ec4ecef0   AKASHI Takahiro   kexec_file,x86,po...
55
56
57
58
59
60
61
62
63
64
65
66
  	return kexec_image_probe_default(image, buf, buf_len);
  }
  
  static void *kexec_image_load_default(struct kimage *image)
  {
  	if (!image->fops || !image->fops->load)
  		return ERR_PTR(-ENOEXEC);
  
  	return image->fops->load(image, image->kernel_buf,
  				 image->kernel_buf_len, image->initrd_buf,
  				 image->initrd_buf_len, image->cmdline_buf,
  				 image->cmdline_buf_len);
a43cac0d9   Dave Young   kexec: split kexe...
67
68
69
70
  }
  
  void * __weak arch_kexec_kernel_image_load(struct kimage *image)
  {
9ec4ecef0   AKASHI Takahiro   kexec_file,x86,po...
71
72
  	return kexec_image_load_default(image);
  }
92a98a2b9   AKASHI Takahiro   kexec_file: make ...
73
  int kexec_image_post_load_cleanup_default(struct kimage *image)
9ec4ecef0   AKASHI Takahiro   kexec_file,x86,po...
74
75
76
77
78
  {
  	if (!image->fops || !image->fops->cleanup)
  		return 0;
  
  	return image->fops->cleanup(image->image_loader_data);
a43cac0d9   Dave Young   kexec: split kexe...
79
80
81
82
  }
  
  int __weak arch_kimage_file_post_load_cleanup(struct kimage *image)
  {
9ec4ecef0   AKASHI Takahiro   kexec_file,x86,po...
83
  	return kexec_image_post_load_cleanup_default(image);
a43cac0d9   Dave Young   kexec: split kexe...
84
  }
99d5cadfd   Jiri Bohac   kexec_file: split...
85
  #ifdef CONFIG_KEXEC_SIG
9ec4ecef0   AKASHI Takahiro   kexec_file,x86,po...
86
87
88
89
90
91
92
93
94
95
96
  static int kexec_image_verify_sig_default(struct kimage *image, void *buf,
  					  unsigned long buf_len)
  {
  	if (!image->fops || !image->fops->verify_sig) {
  		pr_debug("kernel loader does not support signature verification.
  ");
  		return -EKEYREJECTED;
  	}
  
  	return image->fops->verify_sig(buf, buf_len);
  }
a43cac0d9   Dave Young   kexec: split kexe...
97
98
99
  int __weak arch_kexec_kernel_verify_sig(struct kimage *image, void *buf,
  					unsigned long buf_len)
  {
9ec4ecef0   AKASHI Takahiro   kexec_file,x86,po...
100
  	return kexec_image_verify_sig_default(image, buf, buf_len);
a43cac0d9   Dave Young   kexec: split kexe...
101
  }
978e30c9b   Xunlei Pang   kexec: move some ...
102
  #endif
a43cac0d9   Dave Young   kexec: split kexe...
103

8aec395b8   Philipp Rudo   kernel/kexec_file...
104
105
106
107
108
109
110
111
112
  /*
   * arch_kexec_apply_relocations_add - apply relocations of type RELA
   * @pi:		Purgatory to be relocated.
   * @section:	Section relocations applying to.
   * @relsec:	Section containing RELAs.
   * @symtab:	Corresponding symtab.
   *
   * Return: 0 on success, negative errno on error.
   */
a43cac0d9   Dave Young   kexec: split kexe...
113
  int __weak
8aec395b8   Philipp Rudo   kernel/kexec_file...
114
115
  arch_kexec_apply_relocations_add(struct purgatory_info *pi, Elf_Shdr *section,
  				 const Elf_Shdr *relsec, const Elf_Shdr *symtab)
a43cac0d9   Dave Young   kexec: split kexe...
116
117
118
119
120
  {
  	pr_err("RELA relocation unsupported.
  ");
  	return -ENOEXEC;
  }
8aec395b8   Philipp Rudo   kernel/kexec_file...
121
122
123
124
125
126
127
128
129
  /*
   * arch_kexec_apply_relocations - apply relocations of type REL
   * @pi:		Purgatory to be relocated.
   * @section:	Section relocations applying to.
   * @relsec:	Section containing RELs.
   * @symtab:	Corresponding symtab.
   *
   * Return: 0 on success, negative errno on error.
   */
a43cac0d9   Dave Young   kexec: split kexe...
130
  int __weak
8aec395b8   Philipp Rudo   kernel/kexec_file...
131
132
  arch_kexec_apply_relocations(struct purgatory_info *pi, Elf_Shdr *section,
  			     const Elf_Shdr *relsec, const Elf_Shdr *symtab)
a43cac0d9   Dave Young   kexec: split kexe...
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
  {
  	pr_err("REL relocation unsupported.
  ");
  	return -ENOEXEC;
  }
  
  /*
   * Free up memory used by kernel, initrd, and command line. This is temporary
   * memory allocation which is not needed any more after these buffers have
   * been loaded into separate segments and have been copied elsewhere.
   */
  void kimage_file_post_load_cleanup(struct kimage *image)
  {
  	struct purgatory_info *pi = &image->purgatory_info;
  
  	vfree(image->kernel_buf);
  	image->kernel_buf = NULL;
  
  	vfree(image->initrd_buf);
  	image->initrd_buf = NULL;
  
  	kfree(image->cmdline_buf);
  	image->cmdline_buf = NULL;
  
  	vfree(pi->purgatory_buf);
  	pi->purgatory_buf = NULL;
  
  	vfree(pi->sechdrs);
  	pi->sechdrs = NULL;
  
  	/* See if architecture has anything to cleanup post load */
  	arch_kimage_file_post_load_cleanup(image);
  
  	/*
  	 * Above call should have called into bootloader to free up
  	 * any data stored in kimage->image_loader_data. It should
  	 * be ok now to free it up.
  	 */
  	kfree(image->image_loader_data);
  	image->image_loader_data = NULL;
  }
99d5cadfd   Jiri Bohac   kexec_file: split...
174
175
176
177
  #ifdef CONFIG_KEXEC_SIG
  static int
  kimage_validate_signature(struct kimage *image)
  {
99d5cadfd   Jiri Bohac   kexec_file: split...
178
179
180
181
  	int ret;
  
  	ret = arch_kexec_kernel_verify_sig(image, image->kernel_buf,
  					   image->kernel_buf_len);
fd7af71be   Lianbo Jiang   kexec: do not ver...
182
  	if (ret) {
99d5cadfd   Jiri Bohac   kexec_file: split...
183

99d5cadfd   Jiri Bohac   kexec_file: split...
184
  		if (IS_ENABLED(CONFIG_KEXEC_SIG_FORCE)) {
fd7af71be   Lianbo Jiang   kexec: do not ver...
185
186
  			pr_notice("Enforced kernel signature verification failed (%d).
  ", ret);
99d5cadfd   Jiri Bohac   kexec_file: split...
187
188
  			return ret;
  		}
fd7af71be   Lianbo Jiang   kexec: do not ver...
189
190
  		/*
  		 * If IMA is guaranteed to appraise a signature on the kexec
29d3c1c8d   Matthew Garrett   kexec: Allow kexe...
191
192
193
194
195
196
  		 * image, permit it even if the kernel is otherwise locked
  		 * down.
  		 */
  		if (!ima_appraise_signature(READING_KEXEC_IMAGE) &&
  		    security_locked_down(LOCKDOWN_KEXEC))
  			return -EPERM;
fd7af71be   Lianbo Jiang   kexec: do not ver...
197
198
  		pr_debug("kernel signature verification failed (%d).
  ", ret);
99d5cadfd   Jiri Bohac   kexec_file: split...
199
  	}
fd7af71be   Lianbo Jiang   kexec: do not ver...
200
  	return 0;
99d5cadfd   Jiri Bohac   kexec_file: split...
201
202
  }
  #endif
a43cac0d9   Dave Young   kexec: split kexe...
203
204
205
206
207
208
209
210
211
  /*
   * In file mode list of segments is prepared by kernel. Copy relevant
   * data from user space, do error checking, prepare segment list
   */
  static int
  kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd,
  			     const char __user *cmdline_ptr,
  			     unsigned long cmdline_len, unsigned flags)
  {
99d5cadfd   Jiri Bohac   kexec_file: split...
212
  	int ret;
a43cac0d9   Dave Young   kexec: split kexe...
213
  	void *ldata;
0fa8e0846   Kees Cook   fs/kernel_file_re...
214
  	ret = kernel_read_file_from_fd(kernel_fd, 0, &image->kernel_buf,
885352881   Kees Cook   fs/kernel_read_fi...
215
  				       INT_MAX, NULL, READING_KEXEC_IMAGE);
f7a4f689b   Kees Cook   fs/kernel_read_fi...
216
  	if (ret < 0)
a43cac0d9   Dave Young   kexec: split kexe...
217
  		return ret;
f7a4f689b   Kees Cook   fs/kernel_read_fi...
218
  	image->kernel_buf_len = ret;
a43cac0d9   Dave Young   kexec: split kexe...
219
220
221
222
  
  	/* Call arch image probe handlers */
  	ret = arch_kexec_kernel_image_probe(image, image->kernel_buf,
  					    image->kernel_buf_len);
a43cac0d9   Dave Young   kexec: split kexe...
223
224
  	if (ret)
  		goto out;
99d5cadfd   Jiri Bohac   kexec_file: split...
225
226
227
228
  #ifdef CONFIG_KEXEC_SIG
  	ret = kimage_validate_signature(image);
  
  	if (ret)
a43cac0d9   Dave Young   kexec: split kexe...
229
  		goto out;
a43cac0d9   Dave Young   kexec: split kexe...
230
231
232
  #endif
  	/* It is possible that there no initramfs is being loaded */
  	if (!(flags & KEXEC_FILE_NO_INITRAMFS)) {
0fa8e0846   Kees Cook   fs/kernel_file_re...
233
  		ret = kernel_read_file_from_fd(initrd_fd, 0, &image->initrd_buf,
885352881   Kees Cook   fs/kernel_read_fi...
234
  					       INT_MAX, NULL,
b804defe4   Mimi Zohar   kexec: replace ca...
235
  					       READING_KEXEC_INITRAMFS);
f7a4f689b   Kees Cook   fs/kernel_read_fi...
236
  		if (ret < 0)
a43cac0d9   Dave Young   kexec: split kexe...
237
  			goto out;
f7a4f689b   Kees Cook   fs/kernel_read_fi...
238
239
  		image->initrd_buf_len = ret;
  		ret = 0;
a43cac0d9   Dave Young   kexec: split kexe...
240
241
242
  	}
  
  	if (cmdline_len) {
a9bd8dfa5   Al Viro   kimage_file_prepa...
243
244
245
246
  		image->cmdline_buf = memdup_user(cmdline_ptr, cmdline_len);
  		if (IS_ERR(image->cmdline_buf)) {
  			ret = PTR_ERR(image->cmdline_buf);
  			image->cmdline_buf = NULL;
a43cac0d9   Dave Young   kexec: split kexe...
247
248
249
250
251
252
253
254
255
256
  			goto out;
  		}
  
  		image->cmdline_buf_len = cmdline_len;
  
  		/* command line should be a string with last byte null */
  		if (image->cmdline_buf[cmdline_len - 1] != '\0') {
  			ret = -EINVAL;
  			goto out;
  		}
6a31fcd4c   Prakhar Srivastava   KEXEC: Call ima_k...
257

4834177e6   Tyler Hicks   ima: Support addi...
258
  		ima_kexec_cmdline(kernel_fd, image->cmdline_buf,
6a31fcd4c   Prakhar Srivastava   KEXEC: Call ima_k...
259
  				  image->cmdline_buf_len - 1);
a43cac0d9   Dave Young   kexec: split kexe...
260
  	}
6a31fcd4c   Prakhar Srivastava   KEXEC: Call ima_k...
261
262
  	/* IMA needs to pass the measurement list to the next kernel. */
  	ima_add_kexec_buffer(image);
a43cac0d9   Dave Young   kexec: split kexe...
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
  	/* Call arch image load handlers */
  	ldata = arch_kexec_kernel_image_load(image);
  
  	if (IS_ERR(ldata)) {
  		ret = PTR_ERR(ldata);
  		goto out;
  	}
  
  	image->image_loader_data = ldata;
  out:
  	/* In case of error, free up all allocated memory in this function */
  	if (ret)
  		kimage_file_post_load_cleanup(image);
  	return ret;
  }
  
  static int
  kimage_file_alloc_init(struct kimage **rimage, int kernel_fd,
  		       int initrd_fd, const char __user *cmdline_ptr,
  		       unsigned long cmdline_len, unsigned long flags)
  {
  	int ret;
  	struct kimage *image;
  	bool kexec_on_panic = flags & KEXEC_FILE_ON_CRASH;
  
  	image = do_kimage_alloc_init();
  	if (!image)
  		return -ENOMEM;
  
  	image->file_mode = 1;
  
  	if (kexec_on_panic) {
  		/* Enable special crash kernel control page alloc policy. */
  		image->control_page = crashk_res.start;
  		image->type = KEXEC_TYPE_CRASH;
  	}
  
  	ret = kimage_file_prepare_segments(image, kernel_fd, initrd_fd,
  					   cmdline_ptr, cmdline_len, flags);
  	if (ret)
  		goto out_free_image;
  
  	ret = sanity_check_segment_list(image);
  	if (ret)
  		goto out_free_post_load_bufs;
  
  	ret = -ENOMEM;
  	image->control_code_page = kimage_alloc_control_pages(image,
  					   get_order(KEXEC_CONTROL_PAGE_SIZE));
  	if (!image->control_code_page) {
  		pr_err("Could not allocate control_code_buffer
  ");
  		goto out_free_post_load_bufs;
  	}
  
  	if (!kexec_on_panic) {
  		image->swap_page = kimage_alloc_control_pages(image, 0);
  		if (!image->swap_page) {
  			pr_err("Could not allocate swap buffer
  ");
  			goto out_free_control_pages;
  		}
  	}
  
  	*rimage = image;
  	return 0;
  out_free_control_pages:
  	kimage_free_page_list(&image->control_pages);
  out_free_post_load_bufs:
  	kimage_file_post_load_cleanup(image);
  out_free_image:
  	kfree(image);
  	return ret;
  }
  
  SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd,
  		unsigned long, cmdline_len, const char __user *, cmdline_ptr,
  		unsigned long, flags)
  {
  	int ret = 0, i;
  	struct kimage **dest_image, *image;
  
  	/* We only trust the superuser with rebooting the system. */
  	if (!capable(CAP_SYS_BOOT) || kexec_load_disabled)
  		return -EPERM;
  
  	/* Make sure we have a legal set of flags */
  	if (flags != (flags & KEXEC_FILE_FLAGS))
  		return -EINVAL;
  
  	image = NULL;
  
  	if (!mutex_trylock(&kexec_mutex))
  		return -EBUSY;
  
  	dest_image = &kexec_image;
9b492cf58   Xunlei Pang   kexec: introduce ...
359
  	if (flags & KEXEC_FILE_ON_CRASH) {
a43cac0d9   Dave Young   kexec: split kexe...
360
  		dest_image = &kexec_crash_image;
9b492cf58   Xunlei Pang   kexec: introduce ...
361
362
363
  		if (kexec_crash_image)
  			arch_kexec_unprotect_crashkres();
  	}
a43cac0d9   Dave Young   kexec: split kexe...
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
  
  	if (flags & KEXEC_FILE_UNLOAD)
  		goto exchange;
  
  	/*
  	 * In case of crash, new kernel gets loaded in reserved region. It is
  	 * same memory where old crash kernel might be loaded. Free any
  	 * current crash dump kernel before we corrupt it.
  	 */
  	if (flags & KEXEC_FILE_ON_CRASH)
  		kimage_free(xchg(&kexec_crash_image, NULL));
  
  	ret = kimage_file_alloc_init(&image, kernel_fd, initrd_fd, cmdline_ptr,
  				     cmdline_len, flags);
  	if (ret)
  		goto out;
  
  	ret = machine_kexec_prepare(image);
  	if (ret)
  		goto out;
1229384f5   Xunlei Pang   kdump: protect vm...
384
385
386
387
388
389
390
  	/*
  	 * Some architecture(like S390) may touch the crash memory before
  	 * machine_kexec_prepare(), we must copy vmcoreinfo data after it.
  	 */
  	ret = kimage_crash_copy_vmcoreinfo(image);
  	if (ret)
  		goto out;
a43cac0d9   Dave Young   kexec: split kexe...
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
  	ret = kexec_calculate_store_digests(image);
  	if (ret)
  		goto out;
  
  	for (i = 0; i < image->nr_segments; i++) {
  		struct kexec_segment *ksegment;
  
  		ksegment = &image->segment[i];
  		pr_debug("Loading segment %d: buf=0x%p bufsz=0x%zx mem=0x%lx memsz=0x%zx
  ",
  			 i, ksegment->buf, ksegment->bufsz, ksegment->mem,
  			 ksegment->memsz);
  
  		ret = kimage_load_segment(image, &image->segment[i]);
  		if (ret)
  			goto out;
  	}
  
  	kimage_terminate(image);
de68e4dae   Pavel Tatashin   kexec: add machin...
410
411
412
  	ret = machine_kexec_post_load(image);
  	if (ret)
  		goto out;
a43cac0d9   Dave Young   kexec: split kexe...
413
414
415
416
417
418
419
420
  	/*
  	 * Free up any temporary buffers allocated which are not needed
  	 * after image has been loaded
  	 */
  	kimage_file_post_load_cleanup(image);
  exchange:
  	image = xchg(dest_image, image);
  out:
9b492cf58   Xunlei Pang   kexec: introduce ...
421
422
  	if ((flags & KEXEC_FILE_ON_CRASH) && kexec_crash_image)
  		arch_kexec_protect_crashkres();
a43cac0d9   Dave Young   kexec: split kexe...
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
  	mutex_unlock(&kexec_mutex);
  	kimage_free(image);
  	return ret;
  }
  
  static int locate_mem_hole_top_down(unsigned long start, unsigned long end,
  				    struct kexec_buf *kbuf)
  {
  	struct kimage *image = kbuf->image;
  	unsigned long temp_start, temp_end;
  
  	temp_end = min(end, kbuf->buf_max);
  	temp_start = temp_end - kbuf->memsz;
  
  	do {
  		/* align down start */
  		temp_start = temp_start & (~(kbuf->buf_align - 1));
  
  		if (temp_start < start || temp_start < kbuf->buf_min)
  			return 0;
  
  		temp_end = temp_start + kbuf->memsz - 1;
  
  		/*
  		 * Make sure this does not conflict with any of existing
  		 * segments
  		 */
  		if (kimage_is_destination_range(image, temp_start, temp_end)) {
  			temp_start = temp_start - PAGE_SIZE;
  			continue;
  		}
  
  		/* We found a suitable memory range */
  		break;
  	} while (1);
  
  	/* If we are here, we found a suitable memory range */
  	kbuf->mem = temp_start;
  
  	/* Success, stop navigating through remaining System RAM ranges */
  	return 1;
  }
  
  static int locate_mem_hole_bottom_up(unsigned long start, unsigned long end,
  				     struct kexec_buf *kbuf)
  {
  	struct kimage *image = kbuf->image;
  	unsigned long temp_start, temp_end;
  
  	temp_start = max(start, kbuf->buf_min);
  
  	do {
  		temp_start = ALIGN(temp_start, kbuf->buf_align);
  		temp_end = temp_start + kbuf->memsz - 1;
  
  		if (temp_end > end || temp_end > kbuf->buf_max)
  			return 0;
  		/*
  		 * Make sure this does not conflict with any of existing
  		 * segments
  		 */
  		if (kimage_is_destination_range(image, temp_start, temp_end)) {
  			temp_start = temp_start + PAGE_SIZE;
  			continue;
  		}
  
  		/* We found a suitable memory range */
  		break;
  	} while (1);
  
  	/* If we are here, we found a suitable memory range */
  	kbuf->mem = temp_start;
  
  	/* Success, stop navigating through remaining System RAM ranges */
  	return 1;
  }
1d2e733b1   Tom Lendacky   resource: Provide...
499
  static int locate_mem_hole_callback(struct resource *res, void *arg)
a43cac0d9   Dave Young   kexec: split kexe...
500
501
  {
  	struct kexec_buf *kbuf = (struct kexec_buf *)arg;
1d2e733b1   Tom Lendacky   resource: Provide...
502
  	u64 start = res->start, end = res->end;
a43cac0d9   Dave Young   kexec: split kexe...
503
504
505
  	unsigned long sz = end - start + 1;
  
  	/* Returning 0 will take to next memory range */
3fe4f4991   David Hildenbrand   kexec_file: don't...
506
507
  
  	/* Don't use memory that will be detected and handled by a driver. */
7cf603d17   David Hildenbrand   kernel/resource: ...
508
  	if (res->flags & IORESOURCE_SYSRAM_DRIVER_MANAGED)
3fe4f4991   David Hildenbrand   kexec_file: don't...
509
  		return 0;
a43cac0d9   Dave Young   kexec: split kexe...
510
511
512
513
514
515
516
517
518
519
520
521
522
523
  	if (sz < kbuf->memsz)
  		return 0;
  
  	if (end < kbuf->buf_min || start > kbuf->buf_max)
  		return 0;
  
  	/*
  	 * Allocate memory top down with-in ram range. Otherwise bottom up
  	 * allocation.
  	 */
  	if (kbuf->top_down)
  		return locate_mem_hole_top_down(start, end, kbuf);
  	return locate_mem_hole_bottom_up(start, end, kbuf);
  }
350e88bad   Mike Rapoport   mm: memblock: mak...
524
  #ifdef CONFIG_ARCH_KEEP_MEMBLOCK
735c2f90e   AKASHI Takahiro   powerpc, kexec_fi...
525
526
527
528
529
530
531
  static int kexec_walk_memblock(struct kexec_buf *kbuf,
  			       int (*func)(struct resource *, void *))
  {
  	int ret = 0;
  	u64 i;
  	phys_addr_t mstart, mend;
  	struct resource res = { };
497e18586   AKASHI Takahiro   kexec_file: kexec...
532
533
  	if (kbuf->image->type == KEXEC_TYPE_CRASH)
  		return func(&crashk_res, kbuf);
735c2f90e   AKASHI Takahiro   powerpc, kexec_fi...
534
  	if (kbuf->top_down) {
497e18586   AKASHI Takahiro   kexec_file: kexec...
535
  		for_each_free_mem_range_reverse(i, NUMA_NO_NODE, MEMBLOCK_NONE,
735c2f90e   AKASHI Takahiro   powerpc, kexec_fi...
536
537
538
539
540
541
542
543
544
545
546
547
548
  						&mstart, &mend, NULL) {
  			/*
  			 * In memblock, end points to the first byte after the
  			 * range while in kexec, end points to the last byte
  			 * in the range.
  			 */
  			res.start = mstart;
  			res.end = mend - 1;
  			ret = func(&res, kbuf);
  			if (ret)
  				break;
  		}
  	} else {
497e18586   AKASHI Takahiro   kexec_file: kexec...
549
550
  		for_each_free_mem_range(i, NUMA_NO_NODE, MEMBLOCK_NONE,
  					&mstart, &mend, NULL) {
735c2f90e   AKASHI Takahiro   powerpc, kexec_fi...
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
  			/*
  			 * In memblock, end points to the first byte after the
  			 * range while in kexec, end points to the last byte
  			 * in the range.
  			 */
  			res.start = mstart;
  			res.end = mend - 1;
  			ret = func(&res, kbuf);
  			if (ret)
  				break;
  		}
  	}
  
  	return ret;
  }
350e88bad   Mike Rapoport   mm: memblock: mak...
566
567
568
569
570
571
  #else
  static int kexec_walk_memblock(struct kexec_buf *kbuf,
  			       int (*func)(struct resource *, void *))
  {
  	return 0;
  }
735c2f90e   AKASHI Takahiro   powerpc, kexec_fi...
572
  #endif
60fe3910b   Thiago Jung Bauermann   kexec_file: Allow...
573
  /**
735c2f90e   AKASHI Takahiro   powerpc, kexec_fi...
574
   * kexec_walk_resources - call func(data) on free memory regions
60fe3910b   Thiago Jung Bauermann   kexec_file: Allow...
575
576
577
578
579
580
581
   * @kbuf:	Context info for the search. Also passed to @func.
   * @func:	Function to call for each memory region.
   *
   * Return: The memory walk will stop when func returns a non-zero value
   * and that value will be returned. If all free regions are visited without
   * func returning non-zero, then zero will be returned.
   */
735c2f90e   AKASHI Takahiro   powerpc, kexec_fi...
582
583
  static int kexec_walk_resources(struct kexec_buf *kbuf,
  				int (*func)(struct resource *, void *))
60fe3910b   Thiago Jung Bauermann   kexec_file: Allow...
584
585
586
587
588
589
590
591
592
  {
  	if (kbuf->image->type == KEXEC_TYPE_CRASH)
  		return walk_iomem_res_desc(crashk_res.desc,
  					   IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY,
  					   crashk_res.start, crashk_res.end,
  					   kbuf, func);
  	else
  		return walk_system_ram_res(0, ULONG_MAX, kbuf, func);
  }
ec2b9bfaa   Thiago Jung Bauermann   kexec_file: Chang...
593
  /**
e2e806f9e   Thiago Jung Bauermann   kexec_file: Facto...
594
595
596
597
598
599
600
601
602
603
   * kexec_locate_mem_hole - find free memory for the purgatory or the next kernel
   * @kbuf:	Parameters for the memory search.
   *
   * On success, kbuf->mem will have the start address of the memory region found.
   *
   * Return: 0 on success, negative errno on error.
   */
  int kexec_locate_mem_hole(struct kexec_buf *kbuf)
  {
  	int ret;
b6664ba42   AKASHI Takahiro   s390, kexec_file:...
604
605
606
  	/* Arch knows where to place */
  	if (kbuf->mem != KEXEC_BUF_MEM_UNKNOWN)
  		return 0;
350e88bad   Mike Rapoport   mm: memblock: mak...
607
  	if (!IS_ENABLED(CONFIG_ARCH_KEEP_MEMBLOCK))
735c2f90e   AKASHI Takahiro   powerpc, kexec_fi...
608
609
610
  		ret = kexec_walk_resources(kbuf, locate_mem_hole_callback);
  	else
  		ret = kexec_walk_memblock(kbuf, locate_mem_hole_callback);
e2e806f9e   Thiago Jung Bauermann   kexec_file: Facto...
611
612
613
614
615
  
  	return ret == 1 ? 0 : -EADDRNOTAVAIL;
  }
  
  /**
f891f1973   Hari Bathini   kexec_file: Allow...
616
617
618
619
620
621
622
623
624
625
626
627
628
   * arch_kexec_locate_mem_hole - Find free memory to place the segments.
   * @kbuf:                       Parameters for the memory search.
   *
   * On success, kbuf->mem will have the start address of the memory region found.
   *
   * Return: 0 on success, negative errno on error.
   */
  int __weak arch_kexec_locate_mem_hole(struct kexec_buf *kbuf)
  {
  	return kexec_locate_mem_hole(kbuf);
  }
  
  /**
ec2b9bfaa   Thiago Jung Bauermann   kexec_file: Chang...
629
630
631
632
633
634
635
636
   * kexec_add_buffer - place a buffer in a kexec segment
   * @kbuf:	Buffer contents and memory parameters.
   *
   * This function assumes that kexec_mutex is held.
   * On successful return, @kbuf->mem will have the physical address of
   * the buffer in memory.
   *
   * Return: 0 on success, negative errno on error.
a43cac0d9   Dave Young   kexec: split kexe...
637
   */
ec2b9bfaa   Thiago Jung Bauermann   kexec_file: Chang...
638
  int kexec_add_buffer(struct kexec_buf *kbuf)
a43cac0d9   Dave Young   kexec: split kexe...
639
  {
a43cac0d9   Dave Young   kexec: split kexe...
640
  	struct kexec_segment *ksegment;
a43cac0d9   Dave Young   kexec: split kexe...
641
642
643
  	int ret;
  
  	/* Currently adding segment this way is allowed only in file mode */
ec2b9bfaa   Thiago Jung Bauermann   kexec_file: Chang...
644
  	if (!kbuf->image->file_mode)
a43cac0d9   Dave Young   kexec: split kexe...
645
  		return -EINVAL;
ec2b9bfaa   Thiago Jung Bauermann   kexec_file: Chang...
646
  	if (kbuf->image->nr_segments >= KEXEC_SEGMENT_MAX)
a43cac0d9   Dave Young   kexec: split kexe...
647
648
649
650
651
652
653
654
655
  		return -EINVAL;
  
  	/*
  	 * Make sure we are not trying to add buffer after allocating
  	 * control pages. All segments need to be placed first before
  	 * any control pages are allocated. As control page allocation
  	 * logic goes through list of segments to make sure there are
  	 * no destination overlaps.
  	 */
ec2b9bfaa   Thiago Jung Bauermann   kexec_file: Chang...
656
  	if (!list_empty(&kbuf->image->control_pages)) {
a43cac0d9   Dave Young   kexec: split kexe...
657
658
659
  		WARN_ON(1);
  		return -EINVAL;
  	}
ec2b9bfaa   Thiago Jung Bauermann   kexec_file: Chang...
660
661
662
  	/* Ensure minimum alignment needed for segments. */
  	kbuf->memsz = ALIGN(kbuf->memsz, PAGE_SIZE);
  	kbuf->buf_align = max(kbuf->buf_align, PAGE_SIZE);
a43cac0d9   Dave Young   kexec: split kexe...
663
664
  
  	/* Walk the RAM ranges and allocate a suitable range for the buffer */
f891f1973   Hari Bathini   kexec_file: Allow...
665
  	ret = arch_kexec_locate_mem_hole(kbuf);
e2e806f9e   Thiago Jung Bauermann   kexec_file: Facto...
666
667
  	if (ret)
  		return ret;
a43cac0d9   Dave Young   kexec: split kexe...
668
669
  
  	/* Found a suitable memory range */
ec2b9bfaa   Thiago Jung Bauermann   kexec_file: Chang...
670
  	ksegment = &kbuf->image->segment[kbuf->image->nr_segments];
a43cac0d9   Dave Young   kexec: split kexe...
671
672
673
674
  	ksegment->kbuf = kbuf->buffer;
  	ksegment->bufsz = kbuf->bufsz;
  	ksegment->mem = kbuf->mem;
  	ksegment->memsz = kbuf->memsz;
ec2b9bfaa   Thiago Jung Bauermann   kexec_file: Chang...
675
  	kbuf->image->nr_segments++;
a43cac0d9   Dave Young   kexec: split kexe...
676
677
678
679
680
681
682
683
684
685
686
687
688
689
  	return 0;
  }
  
  /* Calculate and store the digest of segments */
  static int kexec_calculate_store_digests(struct kimage *image)
  {
  	struct crypto_shash *tfm;
  	struct shash_desc *desc;
  	int ret = 0, i, j, zero_buf_sz, sha_region_sz;
  	size_t desc_size, nullsz;
  	char *digest;
  	void *zero_buf;
  	struct kexec_sha_region *sha_regions;
  	struct purgatory_info *pi = &image->purgatory_info;
b799a09f6   AKASHI Takahiro   kexec_file: make ...
690
691
  	if (!IS_ENABLED(CONFIG_ARCH_HAS_KEXEC_PURGATORY))
  		return 0;
a43cac0d9   Dave Young   kexec: split kexe...
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
  	zero_buf = __va(page_to_pfn(ZERO_PAGE(0)) << PAGE_SHIFT);
  	zero_buf_sz = PAGE_SIZE;
  
  	tfm = crypto_alloc_shash("sha256", 0, 0);
  	if (IS_ERR(tfm)) {
  		ret = PTR_ERR(tfm);
  		goto out;
  	}
  
  	desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
  	desc = kzalloc(desc_size, GFP_KERNEL);
  	if (!desc) {
  		ret = -ENOMEM;
  		goto out_free_tfm;
  	}
  
  	sha_region_sz = KEXEC_SEGMENT_MAX * sizeof(struct kexec_sha_region);
  	sha_regions = vzalloc(sha_region_sz);
  	if (!sha_regions)
  		goto out_free_desc;
  
  	desc->tfm   = tfm;
a43cac0d9   Dave Young   kexec: split kexe...
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
  
  	ret = crypto_shash_init(desc);
  	if (ret < 0)
  		goto out_free_sha_regions;
  
  	digest = kzalloc(SHA256_DIGEST_SIZE, GFP_KERNEL);
  	if (!digest) {
  		ret = -ENOMEM;
  		goto out_free_sha_regions;
  	}
  
  	for (j = i = 0; i < image->nr_segments; i++) {
  		struct kexec_segment *ksegment;
  
  		ksegment = &image->segment[i];
  		/*
  		 * Skip purgatory as it will be modified once we put digest
  		 * info in purgatory.
  		 */
  		if (ksegment->kbuf == pi->purgatory_buf)
  			continue;
  
  		ret = crypto_shash_update(desc, ksegment->kbuf,
  					  ksegment->bufsz);
  		if (ret)
  			break;
  
  		/*
  		 * Assume rest of the buffer is filled with zero and
  		 * update digest accordingly.
  		 */
  		nullsz = ksegment->memsz - ksegment->bufsz;
  		while (nullsz) {
  			unsigned long bytes = nullsz;
  
  			if (bytes > zero_buf_sz)
  				bytes = zero_buf_sz;
  			ret = crypto_shash_update(desc, zero_buf, bytes);
  			if (ret)
  				break;
  			nullsz -= bytes;
  		}
  
  		if (ret)
  			break;
  
  		sha_regions[j].start = ksegment->mem;
  		sha_regions[j].len = ksegment->memsz;
  		j++;
  	}
  
  	if (!ret) {
  		ret = crypto_shash_final(desc, digest);
  		if (ret)
  			goto out_free_digest;
40c50c1fe   Thomas Gleixner   kexec, x86/purgat...
769
770
  		ret = kexec_purgatory_get_set_symbol(image, "purgatory_sha_regions",
  						     sha_regions, sha_region_sz, 0);
a43cac0d9   Dave Young   kexec: split kexe...
771
772
  		if (ret)
  			goto out_free_digest;
40c50c1fe   Thomas Gleixner   kexec, x86/purgat...
773
774
  		ret = kexec_purgatory_get_set_symbol(image, "purgatory_sha256_digest",
  						     digest, SHA256_DIGEST_SIZE, 0);
a43cac0d9   Dave Young   kexec: split kexe...
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
  		if (ret)
  			goto out_free_digest;
  	}
  
  out_free_digest:
  	kfree(digest);
  out_free_sha_regions:
  	vfree(sha_regions);
  out_free_desc:
  	kfree(desc);
  out_free_tfm:
  	kfree(tfm);
  out:
  	return ret;
  }
b799a09f6   AKASHI Takahiro   kexec_file: make ...
790
  #ifdef CONFIG_ARCH_HAS_KEXEC_PURGATORY
930457057   Philipp Rudo   kernel/kexec_file...
791
792
793
794
795
796
797
798
799
800
801
802
  /*
   * kexec_purgatory_setup_kbuf - prepare buffer to load purgatory.
   * @pi:		Purgatory to be loaded.
   * @kbuf:	Buffer to setup.
   *
   * Allocates the memory needed for the buffer. Caller is responsible to free
   * the memory after use.
   *
   * Return: 0 on success, negative errno on error.
   */
  static int kexec_purgatory_setup_kbuf(struct purgatory_info *pi,
  				      struct kexec_buf *kbuf)
a43cac0d9   Dave Young   kexec: split kexe...
803
  {
930457057   Philipp Rudo   kernel/kexec_file...
804
805
806
807
808
  	const Elf_Shdr *sechdrs;
  	unsigned long bss_align;
  	unsigned long bss_sz;
  	unsigned long align;
  	int i, ret;
a43cac0d9   Dave Young   kexec: split kexe...
809

930457057   Philipp Rudo   kernel/kexec_file...
810
  	sechdrs = (void *)pi->ehdr + pi->ehdr->e_shoff;
3be3f61d2   Philipp Rudo   kernel/kexec_file...
811
812
  	kbuf->buf_align = bss_align = 1;
  	kbuf->bufsz = bss_sz = 0;
930457057   Philipp Rudo   kernel/kexec_file...
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
  
  	for (i = 0; i < pi->ehdr->e_shnum; i++) {
  		if (!(sechdrs[i].sh_flags & SHF_ALLOC))
  			continue;
  
  		align = sechdrs[i].sh_addralign;
  		if (sechdrs[i].sh_type != SHT_NOBITS) {
  			if (kbuf->buf_align < align)
  				kbuf->buf_align = align;
  			kbuf->bufsz = ALIGN(kbuf->bufsz, align);
  			kbuf->bufsz += sechdrs[i].sh_size;
  		} else {
  			if (bss_align < align)
  				bss_align = align;
  			bss_sz = ALIGN(bss_sz, align);
  			bss_sz += sechdrs[i].sh_size;
  		}
  	}
  	kbuf->bufsz = ALIGN(kbuf->bufsz, bss_align);
  	kbuf->memsz = kbuf->bufsz + bss_sz;
  	if (kbuf->buf_align < bss_align)
  		kbuf->buf_align = bss_align;
  
  	kbuf->buffer = vzalloc(kbuf->bufsz);
  	if (!kbuf->buffer)
  		return -ENOMEM;
  	pi->purgatory_buf = kbuf->buffer;
  
  	ret = kexec_add_buffer(kbuf);
  	if (ret)
  		goto out;
930457057   Philipp Rudo   kernel/kexec_file...
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
  
  	return 0;
  out:
  	vfree(pi->purgatory_buf);
  	pi->purgatory_buf = NULL;
  	return ret;
  }
  
  /*
   * kexec_purgatory_setup_sechdrs - prepares the pi->sechdrs buffer.
   * @pi:		Purgatory to be loaded.
   * @kbuf:	Buffer prepared to store purgatory.
   *
   * Allocates the memory needed for the buffer. Caller is responsible to free
   * the memory after use.
   *
   * Return: 0 on success, negative errno on error.
   */
  static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi,
  					 struct kexec_buf *kbuf)
  {
930457057   Philipp Rudo   kernel/kexec_file...
865
866
  	unsigned long bss_addr;
  	unsigned long offset;
930457057   Philipp Rudo   kernel/kexec_file...
867
  	Elf_Shdr *sechdrs;
930457057   Philipp Rudo   kernel/kexec_file...
868
  	int i;
a43cac0d9   Dave Young   kexec: split kexe...
869

8da0b7249   Philipp Rudo   kernel/kexec_file...
870
871
872
873
  	/*
  	 * The section headers in kexec_purgatory are read-only. In order to
  	 * have them modifiable make a temporary copy.
  	 */
fad953ce0   Kees Cook   treewide: Use arr...
874
  	sechdrs = vzalloc(array_size(sizeof(Elf_Shdr), pi->ehdr->e_shnum));
a43cac0d9   Dave Young   kexec: split kexe...
875
876
  	if (!sechdrs)
  		return -ENOMEM;
930457057   Philipp Rudo   kernel/kexec_file...
877
878
879
  	memcpy(sechdrs, (void *)pi->ehdr + pi->ehdr->e_shoff,
  	       pi->ehdr->e_shnum * sizeof(Elf_Shdr));
  	pi->sechdrs = sechdrs;
a43cac0d9   Dave Young   kexec: split kexe...
880

620f697cc   Philipp Rudo   kernel/kexec_file...
881
882
  	offset = 0;
  	bss_addr = kbuf->mem + kbuf->bufsz;
f1b1cca39   Philipp Rudo   kernel/kexec_file...
883
  	kbuf->image->start = pi->ehdr->e_entry;
a43cac0d9   Dave Young   kexec: split kexe...
884
885
  
  	for (i = 0; i < pi->ehdr->e_shnum; i++) {
930457057   Philipp Rudo   kernel/kexec_file...
886
  		unsigned long align;
620f697cc   Philipp Rudo   kernel/kexec_file...
887
  		void *src, *dst;
930457057   Philipp Rudo   kernel/kexec_file...
888

a43cac0d9   Dave Young   kexec: split kexe...
889
890
891
892
  		if (!(sechdrs[i].sh_flags & SHF_ALLOC))
  			continue;
  
  		align = sechdrs[i].sh_addralign;
f1b1cca39   Philipp Rudo   kernel/kexec_file...
893
  		if (sechdrs[i].sh_type == SHT_NOBITS) {
a43cac0d9   Dave Young   kexec: split kexe...
894
895
896
  			bss_addr = ALIGN(bss_addr, align);
  			sechdrs[i].sh_addr = bss_addr;
  			bss_addr += sechdrs[i].sh_size;
f1b1cca39   Philipp Rudo   kernel/kexec_file...
897
898
  			continue;
  		}
620f697cc   Philipp Rudo   kernel/kexec_file...
899
  		offset = ALIGN(offset, align);
f1b1cca39   Philipp Rudo   kernel/kexec_file...
900
901
902
903
904
  		if (sechdrs[i].sh_flags & SHF_EXECINSTR &&
  		    pi->ehdr->e_entry >= sechdrs[i].sh_addr &&
  		    pi->ehdr->e_entry < (sechdrs[i].sh_addr
  					 + sechdrs[i].sh_size)) {
  			kbuf->image->start -= sechdrs[i].sh_addr;
620f697cc   Philipp Rudo   kernel/kexec_file...
905
  			kbuf->image->start += kbuf->mem + offset;
a43cac0d9   Dave Young   kexec: split kexe...
906
  		}
a43cac0d9   Dave Young   kexec: split kexe...
907

8da0b7249   Philipp Rudo   kernel/kexec_file...
908
  		src = (void *)pi->ehdr + sechdrs[i].sh_offset;
620f697cc   Philipp Rudo   kernel/kexec_file...
909
910
911
912
  		dst = pi->purgatory_buf + offset;
  		memcpy(dst, src, sechdrs[i].sh_size);
  
  		sechdrs[i].sh_addr = kbuf->mem + offset;
8da0b7249   Philipp Rudo   kernel/kexec_file...
913
  		sechdrs[i].sh_offset = offset;
620f697cc   Philipp Rudo   kernel/kexec_file...
914
  		offset += sechdrs[i].sh_size;
f1b1cca39   Philipp Rudo   kernel/kexec_file...
915
  	}
a43cac0d9   Dave Young   kexec: split kexe...
916

930457057   Philipp Rudo   kernel/kexec_file...
917
  	return 0;
a43cac0d9   Dave Young   kexec: split kexe...
918
919
920
921
922
923
  }
  
  static int kexec_apply_relocations(struct kimage *image)
  {
  	int i, ret;
  	struct purgatory_info *pi = &image->purgatory_info;
8aec395b8   Philipp Rudo   kernel/kexec_file...
924
925
926
  	const Elf_Shdr *sechdrs;
  
  	sechdrs = (void *)pi->ehdr + pi->ehdr->e_shoff;
a43cac0d9   Dave Young   kexec: split kexe...
927

a43cac0d9   Dave Young   kexec: split kexe...
928
  	for (i = 0; i < pi->ehdr->e_shnum; i++) {
8aec395b8   Philipp Rudo   kernel/kexec_file...
929
930
931
932
933
  		const Elf_Shdr *relsec;
  		const Elf_Shdr *symtab;
  		Elf_Shdr *section;
  
  		relsec = sechdrs + i;
a43cac0d9   Dave Young   kexec: split kexe...
934

8aec395b8   Philipp Rudo   kernel/kexec_file...
935
936
  		if (relsec->sh_type != SHT_RELA &&
  		    relsec->sh_type != SHT_REL)
a43cac0d9   Dave Young   kexec: split kexe...
937
938
939
940
941
942
943
944
  			continue;
  
  		/*
  		 * For section of type SHT_RELA/SHT_REL,
  		 * ->sh_link contains section header index of associated
  		 * symbol table. And ->sh_info contains section header
  		 * index of section to which relocations apply.
  		 */
8aec395b8   Philipp Rudo   kernel/kexec_file...
945
946
  		if (relsec->sh_info >= pi->ehdr->e_shnum ||
  		    relsec->sh_link >= pi->ehdr->e_shnum)
a43cac0d9   Dave Young   kexec: split kexe...
947
  			return -ENOEXEC;
8aec395b8   Philipp Rudo   kernel/kexec_file...
948
949
  		section = pi->sechdrs + relsec->sh_info;
  		symtab = sechdrs + relsec->sh_link;
a43cac0d9   Dave Young   kexec: split kexe...
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
  
  		if (!(section->sh_flags & SHF_ALLOC))
  			continue;
  
  		/*
  		 * symtab->sh_link contain section header index of associated
  		 * string table.
  		 */
  		if (symtab->sh_link >= pi->ehdr->e_shnum)
  			/* Invalid section number? */
  			continue;
  
  		/*
  		 * Respective architecture needs to provide support for applying
  		 * relocations of type SHT_RELA/SHT_REL.
  		 */
8aec395b8   Philipp Rudo   kernel/kexec_file...
966
967
968
969
970
971
  		if (relsec->sh_type == SHT_RELA)
  			ret = arch_kexec_apply_relocations_add(pi, section,
  							       relsec, symtab);
  		else if (relsec->sh_type == SHT_REL)
  			ret = arch_kexec_apply_relocations(pi, section,
  							   relsec, symtab);
a43cac0d9   Dave Young   kexec: split kexe...
972
973
974
975
976
977
  		if (ret)
  			return ret;
  	}
  
  	return 0;
  }
3be3f61d2   Philipp Rudo   kernel/kexec_file...
978
979
980
981
982
983
984
985
986
987
988
989
  /*
   * kexec_load_purgatory - Load and relocate the purgatory object.
   * @image:	Image to add the purgatory to.
   * @kbuf:	Memory parameters to use.
   *
   * Allocates the memory needed for image->purgatory_info.sechdrs and
   * image->purgatory_info.purgatory_buf/kbuf->buffer. Caller is responsible
   * to free the memory after use.
   *
   * Return: 0 on success, negative errno on error.
   */
  int kexec_load_purgatory(struct kimage *image, struct kexec_buf *kbuf)
a43cac0d9   Dave Young   kexec: split kexe...
990
991
992
993
994
995
  {
  	struct purgatory_info *pi = &image->purgatory_info;
  	int ret;
  
  	if (kexec_purgatory_size <= 0)
  		return -EINVAL;
65c225d32   Philipp Rudo   kernel/kexec_file...
996
  	pi->ehdr = (const Elf_Ehdr *)kexec_purgatory;
a43cac0d9   Dave Young   kexec: split kexe...
997

3be3f61d2   Philipp Rudo   kernel/kexec_file...
998
  	ret = kexec_purgatory_setup_kbuf(pi, kbuf);
a43cac0d9   Dave Young   kexec: split kexe...
999
1000
  	if (ret)
  		return ret;
3be3f61d2   Philipp Rudo   kernel/kexec_file...
1001
  	ret = kexec_purgatory_setup_sechdrs(pi, kbuf);
930457057   Philipp Rudo   kernel/kexec_file...
1002
1003
  	if (ret)
  		goto out_free_kbuf;
a43cac0d9   Dave Young   kexec: split kexe...
1004
1005
1006
  	ret = kexec_apply_relocations(image);
  	if (ret)
  		goto out;
a43cac0d9   Dave Young   kexec: split kexe...
1007
1008
1009
  	return 0;
  out:
  	vfree(pi->sechdrs);
070c43eea   Thiago Jung Bauermann   kexec: fix double...
1010
  	pi->sechdrs = NULL;
930457057   Philipp Rudo   kernel/kexec_file...
1011
  out_free_kbuf:
a43cac0d9   Dave Young   kexec: split kexe...
1012
  	vfree(pi->purgatory_buf);
070c43eea   Thiago Jung Bauermann   kexec: fix double...
1013
  	pi->purgatory_buf = NULL;
a43cac0d9   Dave Young   kexec: split kexe...
1014
1015
  	return ret;
  }
961d921a1   Philipp Rudo   kernel/kexec_file...
1016
1017
1018
1019
1020
1021
1022
1023
1024
  /*
   * kexec_purgatory_find_symbol - find a symbol in the purgatory
   * @pi:		Purgatory to search in.
   * @name:	Name of the symbol.
   *
   * Return: pointer to symbol in read-only symtab on success, NULL on error.
   */
  static const Elf_Sym *kexec_purgatory_find_symbol(struct purgatory_info *pi,
  						  const char *name)
a43cac0d9   Dave Young   kexec: split kexe...
1025
  {
961d921a1   Philipp Rudo   kernel/kexec_file...
1026
  	const Elf_Shdr *sechdrs;
65c225d32   Philipp Rudo   kernel/kexec_file...
1027
  	const Elf_Ehdr *ehdr;
961d921a1   Philipp Rudo   kernel/kexec_file...
1028
  	const Elf_Sym *syms;
a43cac0d9   Dave Young   kexec: split kexe...
1029
  	const char *strtab;
961d921a1   Philipp Rudo   kernel/kexec_file...
1030
  	int i, k;
a43cac0d9   Dave Young   kexec: split kexe...
1031

961d921a1   Philipp Rudo   kernel/kexec_file...
1032
  	if (!pi->ehdr)
a43cac0d9   Dave Young   kexec: split kexe...
1033
  		return NULL;
a43cac0d9   Dave Young   kexec: split kexe...
1034
  	ehdr = pi->ehdr;
961d921a1   Philipp Rudo   kernel/kexec_file...
1035
  	sechdrs = (void *)ehdr + ehdr->e_shoff;
a43cac0d9   Dave Young   kexec: split kexe...
1036
1037
1038
1039
1040
1041
1042
1043
  
  	for (i = 0; i < ehdr->e_shnum; i++) {
  		if (sechdrs[i].sh_type != SHT_SYMTAB)
  			continue;
  
  		if (sechdrs[i].sh_link >= ehdr->e_shnum)
  			/* Invalid strtab section number */
  			continue;
961d921a1   Philipp Rudo   kernel/kexec_file...
1044
1045
  		strtab = (void *)ehdr + sechdrs[sechdrs[i].sh_link].sh_offset;
  		syms = (void *)ehdr + sechdrs[i].sh_offset;
a43cac0d9   Dave Young   kexec: split kexe...
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
  
  		/* Go through symbols for a match */
  		for (k = 0; k < sechdrs[i].sh_size/sizeof(Elf_Sym); k++) {
  			if (ELF_ST_BIND(syms[k].st_info) != STB_GLOBAL)
  				continue;
  
  			if (strcmp(strtab + syms[k].st_name, name) != 0)
  				continue;
  
  			if (syms[k].st_shndx == SHN_UNDEF ||
  			    syms[k].st_shndx >= ehdr->e_shnum) {
  				pr_debug("Symbol: %s has bad section index %d.
  ",
  						name, syms[k].st_shndx);
  				return NULL;
  			}
  
  			/* Found the symbol we are looking for */
  			return &syms[k];
  		}
  	}
  
  	return NULL;
  }
  
  void *kexec_purgatory_get_symbol_addr(struct kimage *image, const char *name)
  {
  	struct purgatory_info *pi = &image->purgatory_info;
961d921a1   Philipp Rudo   kernel/kexec_file...
1074
  	const Elf_Sym *sym;
a43cac0d9   Dave Young   kexec: split kexe...
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
  	Elf_Shdr *sechdr;
  
  	sym = kexec_purgatory_find_symbol(pi, name);
  	if (!sym)
  		return ERR_PTR(-EINVAL);
  
  	sechdr = &pi->sechdrs[sym->st_shndx];
  
  	/*
  	 * Returns the address where symbol will finally be loaded after
  	 * kexec_load_segment()
  	 */
  	return (void *)(sechdr->sh_addr + sym->st_value);
  }
  
  /*
   * Get or set value of a symbol. If "get_value" is true, symbol value is
   * returned in buf otherwise symbol value is set based on value in buf.
   */
  int kexec_purgatory_get_set_symbol(struct kimage *image, const char *name,
  				   void *buf, unsigned int size, bool get_value)
  {
a43cac0d9   Dave Young   kexec: split kexe...
1097
  	struct purgatory_info *pi = &image->purgatory_info;
961d921a1   Philipp Rudo   kernel/kexec_file...
1098
1099
  	const Elf_Sym *sym;
  	Elf_Shdr *sec;
a43cac0d9   Dave Young   kexec: split kexe...
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
  	char *sym_buf;
  
  	sym = kexec_purgatory_find_symbol(pi, name);
  	if (!sym)
  		return -EINVAL;
  
  	if (sym->st_size != size) {
  		pr_err("symbol %s size mismatch: expected %lu actual %u
  ",
  		       name, (unsigned long)sym->st_size, size);
  		return -EINVAL;
  	}
961d921a1   Philipp Rudo   kernel/kexec_file...
1112
  	sec = pi->sechdrs + sym->st_shndx;
a43cac0d9   Dave Young   kexec: split kexe...
1113

961d921a1   Philipp Rudo   kernel/kexec_file...
1114
  	if (sec->sh_type == SHT_NOBITS) {
a43cac0d9   Dave Young   kexec: split kexe...
1115
1116
1117
1118
1119
  		pr_err("symbol %s is in a bss section. Cannot %s
  ", name,
  		       get_value ? "get" : "set");
  		return -EINVAL;
  	}
8da0b7249   Philipp Rudo   kernel/kexec_file...
1120
  	sym_buf = (char *)pi->purgatory_buf + sec->sh_offset + sym->st_value;
a43cac0d9   Dave Young   kexec: split kexe...
1121
1122
1123
1124
1125
1126
1127
1128
  
  	if (get_value)
  		memcpy((void *)buf, sym_buf, size);
  	else
  		memcpy((void *)sym_buf, buf, size);
  
  	return 0;
  }
b799a09f6   AKASHI Takahiro   kexec_file: make ...
1129
  #endif /* CONFIG_ARCH_HAS_KEXEC_PURGATORY */
babac4a84   AKASHI Takahiro   kexec_file, x86: ...
1130
1131
1132
1133
1134
  
  int crash_exclude_mem_range(struct crash_mem *mem,
  			    unsigned long long mstart, unsigned long long mend)
  {
  	int i, j;
a2e9a95d2   Lianbo Jiang   kexec: Improve & ...
1135
  	unsigned long long start, end, p_start, p_end;
babac4a84   AKASHI Takahiro   kexec_file, x86: ...
1136
1137
1138
1139
1140
  	struct crash_mem_range temp_range = {0, 0};
  
  	for (i = 0; i < mem->nr_ranges; i++) {
  		start = mem->ranges[i].start;
  		end = mem->ranges[i].end;
a2e9a95d2   Lianbo Jiang   kexec: Improve & ...
1141
1142
  		p_start = mstart;
  		p_end = mend;
babac4a84   AKASHI Takahiro   kexec_file, x86: ...
1143
1144
1145
1146
1147
1148
  
  		if (mstart > end || mend < start)
  			continue;
  
  		/* Truncate any area outside of range */
  		if (mstart < start)
a2e9a95d2   Lianbo Jiang   kexec: Improve & ...
1149
  			p_start = start;
babac4a84   AKASHI Takahiro   kexec_file, x86: ...
1150
  		if (mend > end)
a2e9a95d2   Lianbo Jiang   kexec: Improve & ...
1151
  			p_end = end;
babac4a84   AKASHI Takahiro   kexec_file, x86: ...
1152
1153
  
  		/* Found completely overlapping range */
a2e9a95d2   Lianbo Jiang   kexec: Improve & ...
1154
  		if (p_start == start && p_end == end) {
babac4a84   AKASHI Takahiro   kexec_file, x86: ...
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
  			mem->ranges[i].start = 0;
  			mem->ranges[i].end = 0;
  			if (i < mem->nr_ranges - 1) {
  				/* Shift rest of the ranges to left */
  				for (j = i; j < mem->nr_ranges - 1; j++) {
  					mem->ranges[j].start =
  						mem->ranges[j+1].start;
  					mem->ranges[j].end =
  							mem->ranges[j+1].end;
  				}
a2e9a95d2   Lianbo Jiang   kexec: Improve & ...
1165
1166
1167
1168
1169
1170
1171
1172
1173
  
  				/*
  				 * Continue to check if there are another overlapping ranges
  				 * from the current position because of shifting the above
  				 * mem ranges.
  				 */
  				i--;
  				mem->nr_ranges--;
  				continue;
babac4a84   AKASHI Takahiro   kexec_file, x86: ...
1174
1175
1176
1177
  			}
  			mem->nr_ranges--;
  			return 0;
  		}
a2e9a95d2   Lianbo Jiang   kexec: Improve & ...
1178
  		if (p_start > start && p_end < end) {
babac4a84   AKASHI Takahiro   kexec_file, x86: ...
1179
  			/* Split original range */
a2e9a95d2   Lianbo Jiang   kexec: Improve & ...
1180
1181
  			mem->ranges[i].end = p_start - 1;
  			temp_range.start = p_end + 1;
babac4a84   AKASHI Takahiro   kexec_file, x86: ...
1182
  			temp_range.end = end;
a2e9a95d2   Lianbo Jiang   kexec: Improve & ...
1183
1184
  		} else if (p_start != start)
  			mem->ranges[i].end = p_start - 1;
babac4a84   AKASHI Takahiro   kexec_file, x86: ...
1185
  		else
a2e9a95d2   Lianbo Jiang   kexec: Improve & ...
1186
  			mem->ranges[i].start = p_end + 1;
babac4a84   AKASHI Takahiro   kexec_file, x86: ...
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
  		break;
  	}
  
  	/* If a split happened, add the split to array */
  	if (!temp_range.end)
  		return 0;
  
  	/* Split happened */
  	if (i == mem->max_nr_ranges - 1)
  		return -ENOMEM;
  
  	/* Location where new range should go */
  	j = i + 1;
  	if (j < mem->nr_ranges) {
  		/* Move over all ranges one slot towards the end */
  		for (i = mem->nr_ranges - 1; i >= j; i--)
  			mem->ranges[i + 1] = mem->ranges[i];
  	}
  
  	mem->ranges[j].start = temp_range.start;
  	mem->ranges[j].end = temp_range.end;
  	mem->nr_ranges++;
  	return 0;
  }
  
  int crash_prepare_elf64_headers(struct crash_mem *mem, int kernel_map,
  			  void **addr, unsigned long *sz)
  {
  	Elf64_Ehdr *ehdr;
  	Elf64_Phdr *phdr;
  	unsigned long nr_cpus = num_possible_cpus(), nr_phdr, elf_sz;
  	unsigned char *buf;
  	unsigned int cpu, i;
  	unsigned long long notes_addr;
  	unsigned long mstart, mend;
475f63ae6   Lianbo Jiang   kexec_file: Corre...
1222
  	/* extra phdr for vmcoreinfo ELF note */
babac4a84   AKASHI Takahiro   kexec_file, x86: ...
1223
1224
1225
1226
1227
1228
1229
  	nr_phdr = nr_cpus + 1;
  	nr_phdr += mem->nr_ranges;
  
  	/*
  	 * kexec-tools creates an extra PT_LOAD phdr for kernel text mapping
  	 * area (for example, ffffffff80000000 - ffffffffa0000000 on x86_64).
  	 * I think this is required by tools like gdb. So same physical
475f63ae6   Lianbo Jiang   kexec_file: Corre...
1230
  	 * memory will be mapped in two ELF headers. One will contain kernel
babac4a84   AKASHI Takahiro   kexec_file, x86: ...
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
  	 * text virtual addresses and other will have __va(physical) addresses.
  	 */
  
  	nr_phdr++;
  	elf_sz = sizeof(Elf64_Ehdr) + nr_phdr * sizeof(Elf64_Phdr);
  	elf_sz = ALIGN(elf_sz, ELF_CORE_HEADER_ALIGN);
  
  	buf = vzalloc(elf_sz);
  	if (!buf)
  		return -ENOMEM;
  
  	ehdr = (Elf64_Ehdr *)buf;
  	phdr = (Elf64_Phdr *)(ehdr + 1);
  	memcpy(ehdr->e_ident, ELFMAG, SELFMAG);
  	ehdr->e_ident[EI_CLASS] = ELFCLASS64;
  	ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
  	ehdr->e_ident[EI_VERSION] = EV_CURRENT;
  	ehdr->e_ident[EI_OSABI] = ELF_OSABI;
  	memset(ehdr->e_ident + EI_PAD, 0, EI_NIDENT - EI_PAD);
  	ehdr->e_type = ET_CORE;
  	ehdr->e_machine = ELF_ARCH;
  	ehdr->e_version = EV_CURRENT;
  	ehdr->e_phoff = sizeof(Elf64_Ehdr);
  	ehdr->e_ehsize = sizeof(Elf64_Ehdr);
  	ehdr->e_phentsize = sizeof(Elf64_Phdr);
a2e9a95d2   Lianbo Jiang   kexec: Improve & ...
1256
  	/* Prepare one phdr of type PT_NOTE for each present CPU */
babac4a84   AKASHI Takahiro   kexec_file, x86: ...
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
  	for_each_present_cpu(cpu) {
  		phdr->p_type = PT_NOTE;
  		notes_addr = per_cpu_ptr_to_phys(per_cpu_ptr(crash_notes, cpu));
  		phdr->p_offset = phdr->p_paddr = notes_addr;
  		phdr->p_filesz = phdr->p_memsz = sizeof(note_buf_t);
  		(ehdr->e_phnum)++;
  		phdr++;
  	}
  
  	/* Prepare one PT_NOTE header for vmcoreinfo */
  	phdr->p_type = PT_NOTE;
  	phdr->p_offset = phdr->p_paddr = paddr_vmcoreinfo_note();
  	phdr->p_filesz = phdr->p_memsz = VMCOREINFO_NOTE_SIZE;
  	(ehdr->e_phnum)++;
  	phdr++;
  
  	/* Prepare PT_LOAD type program header for kernel text region */
  	if (kernel_map) {
  		phdr->p_type = PT_LOAD;
  		phdr->p_flags = PF_R|PF_W|PF_X;
f973cce0e   Helge Deller   kexec: Fix pointe...
1277
  		phdr->p_vaddr = (unsigned long) _text;
babac4a84   AKASHI Takahiro   kexec_file, x86: ...
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
  		phdr->p_filesz = phdr->p_memsz = _end - _text;
  		phdr->p_offset = phdr->p_paddr = __pa_symbol(_text);
  		ehdr->e_phnum++;
  		phdr++;
  	}
  
  	/* Go through all the ranges in mem->ranges[] and prepare phdr */
  	for (i = 0; i < mem->nr_ranges; i++) {
  		mstart = mem->ranges[i].start;
  		mend = mem->ranges[i].end;
  
  		phdr->p_type = PT_LOAD;
  		phdr->p_flags = PF_R|PF_W|PF_X;
  		phdr->p_offset  = mstart;
  
  		phdr->p_paddr = mstart;
f973cce0e   Helge Deller   kexec: Fix pointe...
1294
  		phdr->p_vaddr = (unsigned long) __va(mstart);
babac4a84   AKASHI Takahiro   kexec_file, x86: ...
1295
1296
1297
  		phdr->p_filesz = phdr->p_memsz = mend - mstart + 1;
  		phdr->p_align = 0;
  		ehdr->e_phnum++;
475f63ae6   Lianbo Jiang   kexec_file: Corre...
1298
1299
  		pr_debug("Crash PT_LOAD ELF header. phdr=%p vaddr=0x%llx, paddr=0x%llx, sz=0x%llx e_phnum=%d p_offset=0x%llx
  ",
babac4a84   AKASHI Takahiro   kexec_file, x86: ...
1300
1301
  			phdr, phdr->p_vaddr, phdr->p_paddr, phdr->p_filesz,
  			ehdr->e_phnum, phdr->p_offset);
475f63ae6   Lianbo Jiang   kexec_file: Corre...
1302
  		phdr++;
babac4a84   AKASHI Takahiro   kexec_file, x86: ...
1303
1304
1305
1306
1307
1308
  	}
  
  	*addr = buf;
  	*sz = elf_sz;
  	return 0;
  }