1 // SPDX-License-Identifier: GPL-2.0
3 * ELF loader for kexec_file_load system call.
5 * Copyright IBM Corp. 2018
7 * Author(s): Philipp Rudo <prudo@linux.vnet.ibm.com>
10 #include <linux/errno.h>
11 #include <linux/kernel.h>
12 #include <linux/kexec.h>
14 #include <asm/setup.h>
16 static int kexec_file_add_kernel_elf(struct kimage
*image
,
17 struct s390_load_data
*data
)
26 kernel
= image
->kernel_buf
;
27 ehdr
= (Elf_Ehdr
*)kernel
;
29 if (image
->type
== KEXEC_TYPE_CRASH
)
30 entry
= STARTUP_KDUMP_OFFSET
;
32 entry
= ehdr
->e_entry
;
34 phdr
= (void *)ehdr
+ ehdr
->e_phoff
;
35 for (i
= 0; i
< ehdr
->e_phnum
; i
++, phdr
++) {
36 if (phdr
->p_type
!= PT_LOAD
)
39 buf
.buffer
= kernel
+ phdr
->p_offset
;
40 buf
.bufsz
= phdr
->p_filesz
;
42 buf
.mem
= ALIGN(phdr
->p_paddr
, phdr
->p_align
);
43 if (image
->type
== KEXEC_TYPE_CRASH
)
44 buf
.mem
+= crashk_res
.start
;
45 buf
.memsz
= phdr
->p_memsz
;
46 data
->memsz
= ALIGN(data
->memsz
, phdr
->p_align
) + buf
.memsz
;
48 if (entry
- phdr
->p_paddr
< phdr
->p_memsz
) {
49 data
->kernel_buf
= buf
.buffer
;
50 data
->kernel_mem
= buf
.mem
;
51 data
->parm
= buf
.buffer
+ PARMAREA
;
54 ipl_report_add_component(data
->report
, &buf
,
55 IPL_RB_COMPONENT_FLAG_SIGNED
|
56 IPL_RB_COMPONENT_FLAG_VERIFIED
,
58 ret
= kexec_add_buffer(&buf
);
63 return data
->memsz
? 0 : -EINVAL
;
66 static void *s390_elf_load(struct kimage
*image
,
67 char *kernel
, unsigned long kernel_len
,
68 char *initrd
, unsigned long initrd_len
,
69 char *cmdline
, unsigned long cmdline_len
)
76 /* image->fobs->probe already checked for valid ELF magic number. */
77 ehdr
= (Elf_Ehdr
*)kernel
;
79 if (ehdr
->e_type
!= ET_EXEC
||
80 ehdr
->e_ident
[EI_CLASS
] != ELFCLASS64
||
81 !elf_check_arch(ehdr
))
82 return ERR_PTR(-EINVAL
);
84 if (!ehdr
->e_phnum
|| ehdr
->e_phentsize
!= sizeof(Elf_Phdr
))
85 return ERR_PTR(-EINVAL
);
87 size
= ehdr
->e_ehsize
+ ehdr
->e_phoff
;
88 size
+= ehdr
->e_phentsize
* ehdr
->e_phnum
;
89 if (size
> kernel_len
)
90 return ERR_PTR(-EINVAL
);
92 phdr
= (void *)ehdr
+ ehdr
->e_phoff
;
93 size
= ALIGN(size
, phdr
->p_align
);
94 for (i
= 0; i
< ehdr
->e_phnum
; i
++, phdr
++) {
95 if (phdr
->p_type
== PT_INTERP
)
96 return ERR_PTR(-EINVAL
);
98 if (phdr
->p_offset
> kernel_len
)
99 return ERR_PTR(-EINVAL
);
101 size
+= ALIGN(phdr
->p_filesz
, phdr
->p_align
);
104 if (size
> kernel_len
)
105 return ERR_PTR(-EINVAL
);
107 return kexec_file_add_components(image
, kexec_file_add_kernel_elf
);
110 static int s390_elf_probe(const char *buf
, unsigned long len
)
112 const Elf_Ehdr
*ehdr
;
114 if (len
< sizeof(Elf_Ehdr
))
117 ehdr
= (Elf_Ehdr
*)buf
;
119 /* Only check the ELF magic number here and do proper validity check
120 * in the loader. Any check here that fails would send the erroneous
121 * ELF file to the image loader that does not care what it gets.
122 * (Most likely) causing behavior not intended by the user.
124 if (memcmp(ehdr
->e_ident
, ELFMAG
, SELFMAG
) != 0)
130 const struct kexec_file_ops s390_kexec_elf_ops
= {
131 .probe
= s390_elf_probe
,
132 .load
= s390_elf_load
,
133 #ifdef CONFIG_KEXEC_SIG
134 .verify_sig
= s390_verify_sig
,
135 #endif /* CONFIG_KEXEC_SIG */