Commit 0e3f3f8a3d6e778eb3d8599475e6431ad6b51136

Authored by Steven Falco
Committed by Tom Rini
1 parent 16641d52fc

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

... ... @@ -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");