Commit 0e3f3f8a3d6e778eb3d8599475e6431ad6b51136
Committed by
Tom Rini
1 parent
16641d52fc
Exists in
master
and in
53 other branches
Prevent null pointer dereference originating in cmd_pxe.c
Pass a valid cmdtp into do_tftpb(), do_ext2load(), and do_get_fat(), to avoid possible crashes due to null pointer dereferencing. Commit d7884e047d08447dfd1374e9fa2fdf7ab36e56f5 does not go far enough. There is still at least one call chain that can result in a crash. The do_tftpb(), do_ext2load(), and do_get_fat() functions expect a valid cmdtp. Passing in NULL is particularly bad in the do_tftpb() case, because eventually boot_get_kernel() will be called with a NULL cmdtp: do_tftpb() -> netboot_common() -> bootm_maybe_autostart() -> do_bootm() -> do_bootm_states() -> bootm_find_os() -> boot_get_kernel() Around line 991 in cmd_bootm.c, boot_get_kernel() will dereference the null pointer, and the board will crash. Signed-off-by: Steven A. Falco <stevenfalco@gmail.com>
Showing 1 changed file with 42 additions and 42 deletions Side-by-side Diff
common/cmd_pxe.c
... | ... | @@ -114,16 +114,16 @@ |
114 | 114 | return 1; |
115 | 115 | } |
116 | 116 | |
117 | -static int (*do_getfile)(const char *file_path, char *file_addr); | |
117 | +static int (*do_getfile)(cmd_tbl_t *cmdtp, const char *file_path, char *file_addr); | |
118 | 118 | |
119 | -static int do_get_tftp(const char *file_path, char *file_addr) | |
119 | +static int do_get_tftp(cmd_tbl_t *cmdtp, const char *file_path, char *file_addr) | |
120 | 120 | { |
121 | 121 | char *tftp_argv[] = {"tftp", NULL, NULL, NULL}; |
122 | 122 | |
123 | 123 | tftp_argv[1] = file_addr; |
124 | 124 | tftp_argv[2] = (void *)file_path; |
125 | 125 | |
126 | - if (do_tftpb(NULL, 0, 3, tftp_argv)) | |
126 | + if (do_tftpb(cmdtp, 0, 3, tftp_argv)) | |
127 | 127 | return -ENOENT; |
128 | 128 | |
129 | 129 | return 1; |
130 | 130 | |
131 | 131 | |
132 | 132 | |
... | ... | @@ -131,27 +131,27 @@ |
131 | 131 | |
132 | 132 | static char *fs_argv[5]; |
133 | 133 | |
134 | -static int do_get_ext2(const char *file_path, char *file_addr) | |
134 | +static int do_get_ext2(cmd_tbl_t *cmdtp, const char *file_path, char *file_addr) | |
135 | 135 | { |
136 | 136 | #ifdef CONFIG_CMD_EXT2 |
137 | 137 | fs_argv[0] = "ext2load"; |
138 | 138 | fs_argv[3] = file_addr; |
139 | 139 | fs_argv[4] = (void *)file_path; |
140 | 140 | |
141 | - if (!do_ext2load(NULL, 0, 5, fs_argv)) | |
141 | + if (!do_ext2load(cmdtp, 0, 5, fs_argv)) | |
142 | 142 | return 1; |
143 | 143 | #endif |
144 | 144 | return -ENOENT; |
145 | 145 | } |
146 | 146 | |
147 | -static int do_get_fat(const char *file_path, char *file_addr) | |
147 | +static int do_get_fat(cmd_tbl_t *cmdtp, const char *file_path, char *file_addr) | |
148 | 148 | { |
149 | 149 | #ifdef CONFIG_CMD_FAT |
150 | 150 | fs_argv[0] = "fatload"; |
151 | 151 | fs_argv[3] = file_addr; |
152 | 152 | fs_argv[4] = (void *)file_path; |
153 | 153 | |
154 | - if (!do_fat_fsload(NULL, 0, 5, fs_argv)) | |
154 | + if (!do_fat_fsload(cmdtp, 0, 5, fs_argv)) | |
155 | 155 | return 1; |
156 | 156 | #endif |
157 | 157 | return -ENOENT; |
... | ... | @@ -165,7 +165,7 @@ |
165 | 165 | * |
166 | 166 | * Returns 1 for success, or < 0 on error. |
167 | 167 | */ |
168 | -static int get_relfile(const char *file_path, void *file_addr) | |
168 | +static int get_relfile(cmd_tbl_t *cmdtp, const char *file_path, void *file_addr) | |
169 | 169 | { |
170 | 170 | size_t path_len; |
171 | 171 | char relfile[MAX_TFTP_PATH_LEN+1]; |
... | ... | @@ -194,7 +194,7 @@ |
194 | 194 | |
195 | 195 | sprintf(addr_buf, "%p", file_addr); |
196 | 196 | |
197 | - return do_getfile(relfile, addr_buf); | |
197 | + return do_getfile(cmdtp, relfile, addr_buf); | |
198 | 198 | } |
199 | 199 | |
200 | 200 | /* |
201 | 201 | |
... | ... | @@ -204,13 +204,13 @@ |
204 | 204 | * |
205 | 205 | * Returns 1 on success, or < 0 for error. |
206 | 206 | */ |
207 | -static int get_pxe_file(const char *file_path, void *file_addr) | |
207 | +static int get_pxe_file(cmd_tbl_t *cmdtp, const char *file_path, void *file_addr) | |
208 | 208 | { |
209 | 209 | unsigned long config_file_size; |
210 | 210 | char *tftp_filesize; |
211 | 211 | int err; |
212 | 212 | |
213 | - err = get_relfile(file_path, file_addr); | |
213 | + err = get_relfile(cmdtp, file_path, file_addr); | |
214 | 214 | |
215 | 215 | if (err < 0) |
216 | 216 | return err; |
... | ... | @@ -241,7 +241,7 @@ |
241 | 241 | * |
242 | 242 | * Returns 1 on success or < 0 on error. |
243 | 243 | */ |
244 | -static int get_pxelinux_path(const char *file, void *pxefile_addr_r) | |
244 | +static int get_pxelinux_path(cmd_tbl_t *cmdtp, const char *file, void *pxefile_addr_r) | |
245 | 245 | { |
246 | 246 | size_t base_len = strlen(PXELINUX_DIR); |
247 | 247 | char path[MAX_TFTP_PATH_LEN+1]; |
... | ... | @@ -254,7 +254,7 @@ |
254 | 254 | |
255 | 255 | sprintf(path, PXELINUX_DIR "%s", file); |
256 | 256 | |
257 | - return get_pxe_file(path, pxefile_addr_r); | |
257 | + return get_pxe_file(cmdtp, path, pxefile_addr_r); | |
258 | 258 | } |
259 | 259 | |
260 | 260 | /* |
... | ... | @@ -262,7 +262,7 @@ |
262 | 262 | * |
263 | 263 | * Returns 1 on success or < 0 on error. |
264 | 264 | */ |
265 | -static int pxe_uuid_path(void *pxefile_addr_r) | |
265 | +static int pxe_uuid_path(cmd_tbl_t *cmdtp, void *pxefile_addr_r) | |
266 | 266 | { |
267 | 267 | char *uuid_str; |
268 | 268 | |
... | ... | @@ -271,7 +271,7 @@ |
271 | 271 | if (!uuid_str) |
272 | 272 | return -ENOENT; |
273 | 273 | |
274 | - return get_pxelinux_path(uuid_str, pxefile_addr_r); | |
274 | + return get_pxelinux_path(cmdtp, uuid_str, pxefile_addr_r); | |
275 | 275 | } |
276 | 276 | |
277 | 277 | /* |
... | ... | @@ -280,7 +280,7 @@ |
280 | 280 | * |
281 | 281 | * Returns 1 on success or < 0 on error. |
282 | 282 | */ |
283 | -static int pxe_mac_path(void *pxefile_addr_r) | |
283 | +static int pxe_mac_path(cmd_tbl_t *cmdtp, void *pxefile_addr_r) | |
284 | 284 | { |
285 | 285 | char mac_str[21]; |
286 | 286 | int err; |
... | ... | @@ -290,7 +290,7 @@ |
290 | 290 | if (err < 0) |
291 | 291 | return err; |
292 | 292 | |
293 | - return get_pxelinux_path(mac_str, pxefile_addr_r); | |
293 | + return get_pxelinux_path(cmdtp, mac_str, pxefile_addr_r); | |
294 | 294 | } |
295 | 295 | |
296 | 296 | /* |
... | ... | @@ -300,7 +300,7 @@ |
300 | 300 | * |
301 | 301 | * Returns 1 on success or < 0 on error. |
302 | 302 | */ |
303 | -static int pxe_ipaddr_paths(void *pxefile_addr_r) | |
303 | +static int pxe_ipaddr_paths(cmd_tbl_t *cmdtp, void *pxefile_addr_r) | |
304 | 304 | { |
305 | 305 | char ip_addr[9]; |
306 | 306 | int mask_pos, err; |
... | ... | @@ -308,7 +308,7 @@ |
308 | 308 | sprintf(ip_addr, "%08X", ntohl(NetOurIP)); |
309 | 309 | |
310 | 310 | for (mask_pos = 7; mask_pos >= 0; mask_pos--) { |
311 | - err = get_pxelinux_path(ip_addr, pxefile_addr_r); | |
311 | + err = get_pxelinux_path(cmdtp, ip_addr, pxefile_addr_r); | |
312 | 312 | |
313 | 313 | if (err > 0) |
314 | 314 | return err; |
315 | 315 | |
... | ... | @@ -359,16 +359,16 @@ |
359 | 359 | * Keep trying paths until we successfully get a file we're looking |
360 | 360 | * for. |
361 | 361 | */ |
362 | - if (pxe_uuid_path((void *)pxefile_addr_r) > 0 || | |
363 | - pxe_mac_path((void *)pxefile_addr_r) > 0 || | |
364 | - pxe_ipaddr_paths((void *)pxefile_addr_r) > 0) { | |
362 | + if (pxe_uuid_path(cmdtp, (void *)pxefile_addr_r) > 0 || | |
363 | + pxe_mac_path(cmdtp, (void *)pxefile_addr_r) > 0 || | |
364 | + pxe_ipaddr_paths(cmdtp, (void *)pxefile_addr_r) > 0) { | |
365 | 365 | printf("Config file found\n"); |
366 | 366 | |
367 | 367 | return 0; |
368 | 368 | } |
369 | 369 | |
370 | 370 | while (pxe_default_paths[i]) { |
371 | - if (get_pxelinux_path(pxe_default_paths[i], | |
371 | + if (get_pxelinux_path(cmdtp, pxe_default_paths[i], | |
372 | 372 | (void *)pxefile_addr_r) > 0) { |
373 | 373 | printf("Config file found\n"); |
374 | 374 | return 0; |
... | ... | @@ -388,7 +388,7 @@ |
388 | 388 | * |
389 | 389 | * Returns 1 on success or < 0 on error. |
390 | 390 | */ |
391 | -static int get_relfile_envaddr(const char *file_path, const char *envaddr_name) | |
391 | +static int get_relfile_envaddr(cmd_tbl_t *cmdtp, const char *file_path, const char *envaddr_name) | |
392 | 392 | { |
393 | 393 | unsigned long file_addr; |
394 | 394 | char *envaddr; |
... | ... | @@ -401,7 +401,7 @@ |
401 | 401 | if (strict_strtoul(envaddr, 16, &file_addr) < 0) |
402 | 402 | return -EINVAL; |
403 | 403 | |
404 | - return get_relfile(file_path, (void *)file_addr); | |
404 | + return get_relfile(cmdtp, file_path, (void *)file_addr); | |
405 | 405 | } |
406 | 406 | |
407 | 407 | /* |
... | ... | @@ -599,7 +599,7 @@ |
599 | 599 | } |
600 | 600 | |
601 | 601 | if (label->initrd) { |
602 | - if (get_relfile_envaddr(label->initrd, "ramdisk_addr_r") < 0) { | |
602 | + if (get_relfile_envaddr(cmdtp, label->initrd, "ramdisk_addr_r") < 0) { | |
603 | 603 | printf("Skipping %s for failure retrieving initrd\n", |
604 | 604 | label->name); |
605 | 605 | return 1; |
... | ... | @@ -613,7 +613,7 @@ |
613 | 613 | bootm_argv[2] = "-"; |
614 | 614 | } |
615 | 615 | |
616 | - if (get_relfile_envaddr(label->kernel, "kernel_addr_r") < 0) { | |
616 | + if (get_relfile_envaddr(cmdtp, label->kernel, "kernel_addr_r") < 0) { | |
617 | 617 | printf("Skipping %s for failure retrieving kernel\n", |
618 | 618 | label->name); |
619 | 619 | return 1; |
... | ... | @@ -673,7 +673,7 @@ |
673 | 673 | |
674 | 674 | /* if fdt label is defined then get fdt from server */ |
675 | 675 | if (bootm_argv[3] && label->fdt) { |
676 | - if (get_relfile_envaddr(label->fdt, "fdt_addr_r") < 0) { | |
676 | + if (get_relfile_envaddr(cmdtp, label->fdt, "fdt_addr_r") < 0) { | |
677 | 677 | printf("Skipping %s for failure retrieving fdt\n", |
678 | 678 | label->name); |
679 | 679 | return 1; |
... | ... | @@ -950,7 +950,7 @@ |
950 | 950 | return 1; |
951 | 951 | } |
952 | 952 | |
953 | -static int parse_pxefile_top(char *p, struct pxe_menu *cfg, int nest_level); | |
953 | +static int parse_pxefile_top(cmd_tbl_t *cmdtp, char *p, struct pxe_menu *cfg, int nest_level); | |
954 | 954 | |
955 | 955 | /* |
956 | 956 | * Parse an include statement, and retrieve and parse the file it mentions. |
... | ... | @@ -960,7 +960,7 @@ |
960 | 960 | * include, nest_level has already been incremented and doesn't need to be |
961 | 961 | * incremented here. |
962 | 962 | */ |
963 | -static int handle_include(char **c, char *base, | |
963 | +static int handle_include(cmd_tbl_t *cmdtp, char **c, char *base, | |
964 | 964 | struct pxe_menu *cfg, int nest_level) |
965 | 965 | { |
966 | 966 | char *include_path; |
967 | 967 | |
... | ... | @@ -975,14 +975,14 @@ |
975 | 975 | return err; |
976 | 976 | } |
977 | 977 | |
978 | - err = get_pxe_file(include_path, base); | |
978 | + err = get_pxe_file(cmdtp, include_path, base); | |
979 | 979 | |
980 | 980 | if (err < 0) { |
981 | 981 | printf("Couldn't retrieve %s\n", include_path); |
982 | 982 | return err; |
983 | 983 | } |
984 | 984 | |
985 | - return parse_pxefile_top(base, cfg, nest_level); | |
985 | + return parse_pxefile_top(cmdtp, base, cfg, nest_level); | |
986 | 986 | } |
987 | 987 | |
988 | 988 | /* |
... | ... | @@ -995,7 +995,7 @@ |
995 | 995 | * nest_level should be 1 when parsing the top level pxe file, 2 when parsing |
996 | 996 | * a file it includes, 3 when parsing a file included by that file, and so on. |
997 | 997 | */ |
998 | -static int parse_menu(char **c, struct pxe_menu *cfg, char *b, int nest_level) | |
998 | +static int parse_menu(cmd_tbl_t *cmdtp, char **c, struct pxe_menu *cfg, char *b, int nest_level) | |
999 | 999 | { |
1000 | 1000 | struct token t; |
1001 | 1001 | char *s = *c; |
... | ... | @@ -1010,7 +1010,7 @@ |
1010 | 1010 | break; |
1011 | 1011 | |
1012 | 1012 | case T_INCLUDE: |
1013 | - err = handle_include(c, b + strlen(b) + 1, cfg, | |
1013 | + err = handle_include(cmdtp, c, b + strlen(b) + 1, cfg, | |
1014 | 1014 | nest_level + 1); |
1015 | 1015 | break; |
1016 | 1016 | |
... | ... | @@ -1172,7 +1172,7 @@ |
1172 | 1172 | * |
1173 | 1173 | * Returns 1 on success, < 0 on error. |
1174 | 1174 | */ |
1175 | -static int parse_pxefile_top(char *p, struct pxe_menu *cfg, int nest_level) | |
1175 | +static int parse_pxefile_top(cmd_tbl_t *cmdtp, char *p, struct pxe_menu *cfg, int nest_level) | |
1176 | 1176 | { |
1177 | 1177 | struct token t; |
1178 | 1178 | char *s, *b, *label_name; |
... | ... | @@ -1194,7 +1194,7 @@ |
1194 | 1194 | switch (t.type) { |
1195 | 1195 | case T_MENU: |
1196 | 1196 | cfg->prompt = 1; |
1197 | - err = parse_menu(&p, cfg, b, nest_level); | |
1197 | + err = parse_menu(cmdtp, &p, cfg, b, nest_level); | |
1198 | 1198 | break; |
1199 | 1199 | |
1200 | 1200 | case T_TIMEOUT: |
... | ... | @@ -1219,7 +1219,7 @@ |
1219 | 1219 | break; |
1220 | 1220 | |
1221 | 1221 | case T_INCLUDE: |
1222 | - err = handle_include(&p, b + ALIGN(strlen(b), 4), cfg, | |
1222 | + err = handle_include(cmdtp, &p, b + ALIGN(strlen(b), 4), cfg, | |
1223 | 1223 | nest_level + 1); |
1224 | 1224 | break; |
1225 | 1225 | |
... | ... | @@ -1276,7 +1276,7 @@ |
1276 | 1276 | * files it includes). The resulting pxe_menu struct can be free()'d by using |
1277 | 1277 | * the destroy_pxe_menu() function. |
1278 | 1278 | */ |
1279 | -static struct pxe_menu *parse_pxefile(char *menucfg) | |
1279 | +static struct pxe_menu *parse_pxefile(cmd_tbl_t *cmdtp, char *menucfg) | |
1280 | 1280 | { |
1281 | 1281 | struct pxe_menu *cfg; |
1282 | 1282 | |
... | ... | @@ -1289,7 +1289,7 @@ |
1289 | 1289 | |
1290 | 1290 | INIT_LIST_HEAD(&cfg->labels); |
1291 | 1291 | |
1292 | - if (parse_pxefile_top(menucfg, cfg, 1) < 0) { | |
1292 | + if (parse_pxefile_top(cmdtp, menucfg, cfg, 1) < 0) { | |
1293 | 1293 | destroy_pxe_menu(cfg); |
1294 | 1294 | return NULL; |
1295 | 1295 | } |
... | ... | @@ -1446,7 +1446,7 @@ |
1446 | 1446 | return 1; |
1447 | 1447 | } |
1448 | 1448 | |
1449 | - cfg = parse_pxefile((char *)(pxefile_addr_r)); | |
1449 | + cfg = parse_pxefile(cmdtp, (char *)(pxefile_addr_r)); | |
1450 | 1450 | |
1451 | 1451 | if (cfg == NULL) { |
1452 | 1452 | printf("Error parsing config file\n"); |
1453 | 1453 | |
... | ... | @@ -1544,12 +1544,12 @@ |
1544 | 1544 | return 1; |
1545 | 1545 | } |
1546 | 1546 | |
1547 | - if (get_pxe_file(filename, (void *)pxefile_addr_r) < 0) { | |
1547 | + if (get_pxe_file(cmdtp, filename, (void *)pxefile_addr_r) < 0) { | |
1548 | 1548 | printf("Error reading config file\n"); |
1549 | 1549 | return 1; |
1550 | 1550 | } |
1551 | 1551 | |
1552 | - cfg = parse_pxefile((char *)(pxefile_addr_r)); | |
1552 | + cfg = parse_pxefile(cmdtp, (char *)(pxefile_addr_r)); | |
1553 | 1553 | |
1554 | 1554 | if (cfg == NULL) { |
1555 | 1555 | printf("Error parsing config file\n"); |