]> git.proxmox.com Git - grub2.git/blob - util/grub-module-verifier.c
fs/ntfs: Fix various OOB reads and writes (CVE-2023-4692, CVE-2023-4693)
[grub2.git] / util / grub-module-verifier.c
1 #include <stdio.h>
2 #include <string.h>
3
4 #include <grub/elf.h>
5 #include <grub/module_verifier.h>
6 #include <grub/misc.h>
7 #include <grub/util/misc.h>
8
9 struct grub_module_verifier_arch archs[] = {
10 { "i386", 4, 0, EM_386, GRUB_MODULE_VERIFY_SUPPORTS_REL, (int[]){
11 R_386_32,
12 R_386_PC32,
13 -1
14 } },
15 { "x86_64", 8, 0, EM_X86_64, GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
16 R_X86_64_64,
17 R_X86_64_PC64,
18 /* R_X86_64_32, R_X86_64_32S are supported but shouldn't be used because of their limited range. */
19 -1
20 }, (int[]){
21 R_X86_64_PC32,
22 R_X86_64_PLT32,
23 -1
24 }
25 },
26 { "powerpc", 4, 1, EM_PPC, GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
27 GRUB_ELF_R_PPC_ADDR16_LO,
28 GRUB_ELF_R_PPC_REL24, /* It has limited range but GRUB adds trampolines when necessarry. */
29 GRUB_ELF_R_PPC_ADDR16_HA,
30 GRUB_ELF_R_PPC_ADDR32,
31 GRUB_ELF_R_PPC_REL32,
32 GRUB_ELF_R_PPC_PLTREL24,
33 -1
34 } },
35 { "sparc64", 8, 1, EM_SPARCV9, GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
36 R_SPARC_WDISP30, /* It has limited range but GRUB adds trampolines when necessarry. */
37 R_SPARC_HH22,
38 R_SPARC_HM10,
39 R_SPARC_LM22,
40 R_SPARC_LO10,
41 R_SPARC_64,
42 R_SPARC_OLO10,
43 /* Following 2 relocations have limited range but unfortunately
44 clang generates them, as it doesn't implement mcmodel=large properly.
45 At least our heap and core are under 4G, so it's not a problem
46 usually. */
47 R_SPARC_HI22,
48 R_SPARC_32,
49 -1
50 } },
51 { "ia64", 8, 0, EM_IA_64, GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
52 R_IA64_PCREL21B, /* We should verify that it's pointing either
53 to a function or to a section in the same module.
54 Checking that external symbol is a function is
55 non-trivial and I have never seen this relocation used
56 for anything else, so assume that it always points to a
57 function.
58 */
59 R_IA64_SEGREL64LSB,
60 R_IA64_FPTR64LSB,
61 R_IA64_DIR64LSB,
62 R_IA64_PCREL64LSB,
63 R_IA64_LTOFF22X,
64 R_IA64_LTOFF22,
65 R_IA64_GPREL64I,
66 R_IA64_LTOFF_FPTR22,
67 R_IA64_LDXMOV,
68 -1
69 }, (int[]){
70 R_IA64_GPREL22,
71 -1
72 } },
73 { "mipsel", 4, 0, EM_MIPS, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
74 R_MIPS_HI16,
75 R_MIPS_LO16,
76 R_MIPS_32,
77 R_MIPS_GPREL32,
78 R_MIPS_26,
79 R_MIPS_GOT16,
80 R_MIPS_CALL16,
81 R_MIPS_JALR,
82 -1
83 } },
84 { "mips", 4, 1, EM_MIPS, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
85 R_MIPS_HI16,
86 R_MIPS_LO16,
87 R_MIPS_32,
88 R_MIPS_GPREL32,
89 R_MIPS_26,
90 R_MIPS_GOT16,
91 R_MIPS_CALL16,
92 R_MIPS_JALR,
93 -1
94 } },
95 { "arm", 4, 0, EM_ARM, GRUB_MODULE_VERIFY_SUPPORTS_REL, (int[]){
96 /* Some relocations are range-limited but trampolines are added when necessarry. */
97 R_ARM_ABS32,
98 R_ARM_CALL,
99 R_ARM_JUMP24,
100 R_ARM_THM_CALL,
101 R_ARM_THM_JUMP24,
102 R_ARM_V4BX,
103 R_ARM_THM_MOVW_ABS_NC,
104 R_ARM_THM_MOVT_ABS,
105 R_ARM_THM_JUMP19,
106 -1
107 } },
108 { "arm64", 8, 0, EM_AARCH64, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
109 R_AARCH64_ABS64,
110 R_AARCH64_CALL26,
111 R_AARCH64_JUMP26,
112 R_AARCH64_ADR_GOT_PAGE,
113 R_AARCH64_LD64_GOT_LO12_NC,
114 -1
115 }, (int[]){
116 R_AARCH64_ADR_PREL_PG_HI21,
117 R_AARCH64_ADD_ABS_LO12_NC,
118 R_AARCH64_LDST64_ABS_LO12_NC,
119 R_AARCH64_PREL32,
120 -1
121 } },
122 { "riscv32", 4, 0, EM_RISCV, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
123 R_RISCV_32,
124 R_RISCV_64,
125 R_RISCV_ADD8,
126 R_RISCV_ADD16,
127 R_RISCV_ADD32,
128 R_RISCV_ADD64,
129 R_RISCV_SUB8,
130 R_RISCV_SUB16,
131 R_RISCV_SUB32,
132 R_RISCV_SUB64,
133 R_RISCV_ALIGN,
134 R_RISCV_BRANCH,
135 R_RISCV_CALL,
136 R_RISCV_CALL_PLT,
137 R_RISCV_GOT_HI20,
138 R_RISCV_HI20,
139 R_RISCV_JAL,
140 R_RISCV_LO12_I,
141 R_RISCV_LO12_S,
142 R_RISCV_PCREL_HI20,
143 R_RISCV_PCREL_LO12_I,
144 R_RISCV_PCREL_LO12_S,
145 R_RISCV_RELAX,
146 R_RISCV_RVC_BRANCH,
147 R_RISCV_RVC_JUMP,
148 -1
149 } },
150 { "riscv64", 8, 0, EM_RISCV, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
151 R_RISCV_32,
152 R_RISCV_64,
153 R_RISCV_ADD8,
154 R_RISCV_ADD16,
155 R_RISCV_ADD32,
156 R_RISCV_ADD64,
157 R_RISCV_SUB8,
158 R_RISCV_SUB16,
159 R_RISCV_SUB32,
160 R_RISCV_SUB64,
161 R_RISCV_ALIGN,
162 R_RISCV_BRANCH,
163 R_RISCV_CALL,
164 R_RISCV_CALL_PLT,
165 R_RISCV_GOT_HI20,
166 R_RISCV_HI20,
167 R_RISCV_JAL,
168 R_RISCV_LO12_I,
169 R_RISCV_LO12_S,
170 R_RISCV_PCREL_HI20,
171 R_RISCV_PCREL_LO12_I,
172 R_RISCV_PCREL_LO12_S,
173 R_RISCV_RELAX,
174 R_RISCV_RVC_BRANCH,
175 R_RISCV_RVC_JUMP,
176 -1
177 }
178 },
179 };
180
181 struct platform_whitelist {
182 const char *arch;
183 const char *platform;
184 const char **whitelist_empty;
185 };
186
187 static struct platform_whitelist whitelists[] = {
188 {"i386", "xen", (const char *[]) {"all_video", 0}},
189 {"i386", "xen_pvh", (const char *[]) {"all_video", 0}},
190 {"x86_64", "xen", (const char *[]) {"all_video", 0}},
191 {"sparc64", "ieee1275", (const char *[]) {"all_video", 0}},
192
193 /* video is compiled-in on MIPS. */
194 {"mipsel", "loongson", (const char *[]) {"all_video", 0}},
195 {"mipsel", "qemu_mips", (const char *[]) {"all_video", 0}},
196 {"mipsel", "arc", (const char *[]) {"all_video", 0}},
197 {"mips", "qemu_mips", (const char *[]) {"all_video", 0}},
198 {"mips", "arc", (const char *[]) {"all_video", 0}},
199 };
200
201
202 int
203 main (int argc, char **argv)
204 {
205 size_t module_size;
206 unsigned arch, whitelist;
207 const char **whitelist_empty = 0;
208 char *module_img;
209 if (argc != 4) {
210 fprintf (stderr, "usage: %s FILE ARCH PLATFORM\n", argv[0]);
211 return 1;
212 }
213
214 for (arch = 0; arch < ARRAY_SIZE(archs); arch++)
215 if (strcmp(archs[arch].name, argv[2]) == 0)
216 break;
217 if (arch == ARRAY_SIZE(archs))
218 grub_util_error("%s: unknown arch: %s", argv[1], argv[2]);
219
220 for (whitelist = 0; whitelist < ARRAY_SIZE(whitelists); whitelist++)
221 if (strcmp(whitelists[whitelist].arch, argv[2]) == 0
222 && strcmp(whitelists[whitelist].platform, argv[3]) == 0)
223 break;
224 if (whitelist != ARRAY_SIZE(whitelists))
225 whitelist_empty = whitelists[whitelist].whitelist_empty;
226
227 module_size = grub_util_get_image_size (argv[1]);
228 module_img = grub_util_read_image (argv[1]);
229 if (archs[arch].voidp_sizeof == 8)
230 grub_module_verify64(argv[1], module_img, module_size, &archs[arch], whitelist_empty);
231 else
232 grub_module_verify32(argv[1], module_img, module_size, &archs[arch], whitelist_empty);
233 return 0;
234 }