瀏覽代碼

env: fix potential stack overflow in environment functions

Most of the various environment functions create CONFIG_ENV_SIZE buffers on
the stack. At least on ARM and PPC which have 4KB stacks, this can overflow
the stack if we have large environment sizes. So move all the buffers off
the stack to static buffers.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Rob Herring 12 年之前
父節點
當前提交
60d7d5a631
共有 8 個文件被更改,包括 74 次插入63 次删除
  1. 7 8
      common/env_dataflash.c
  2. 7 6
      common/env_eeprom.c
  3. 6 5
      common/env_fat.c
  4. 7 6
      common/env_mmc.c
  5. 12 11
      common/env_nand.c
  6. 16 10
      common/env_nvram.c
  7. 7 6
      common/env_onenand.c
  8. 12 11
      common/env_sf.c

+ 7 - 8
common/env_dataflash.c

@@ -30,6 +30,7 @@ DECLARE_GLOBAL_DATA_PTR;
 env_t *env_ptr;
 
 char *env_name_spec = "dataflash";
+static char env_buf[CONFIG_ENV_SIZE];
 
 uchar env_get_char_spec(int index)
 {
@@ -42,11 +43,9 @@ uchar env_get_char_spec(int index)
 
 void env_relocate_spec(void)
 {
-	char buf[CONFIG_ENV_SIZE];
+	read_dataflash(CONFIG_ENV_ADDR, CONFIG_ENV_SIZE, env_buf);
 
-	read_dataflash(CONFIG_ENV_ADDR, CONFIG_ENV_SIZE, buf);
-
-	env_import(buf, 1);
+	env_import(env_buf, 1);
 }
 
 #ifdef CONFIG_ENV_OFFSET_REDUND
@@ -55,20 +54,20 @@ void env_relocate_spec(void)
 
 int saveenv(void)
 {
-	env_t	env_new;
+	env_t	*env_new = (env_t *)env_buf;
 	ssize_t	len;
 	char	*res;
 
-	res = (char *)&env_new.data;
+	res = (char *)env_new->data;
 	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
 	if (len < 0) {
 		error("Cannot export environment: errno = %d\n", errno);
 		return 1;
 	}
-	env_new.crc = crc32(0, env_new.data, ENV_SIZE);
+	env_new->crc = crc32(0, env_new->data, ENV_SIZE);
 
 	return write_dataflash(CONFIG_ENV_ADDR,
-				(unsigned long)&env_new,
+				(unsigned long)env_new,
 				CONFIG_ENV_SIZE);
 }
 

+ 7 - 6
common/env_eeprom.c

@@ -38,6 +38,7 @@
 DECLARE_GLOBAL_DATA_PTR;
 
 env_t *env_ptr;
+static char env_buf[CONFIG_ENV_SIZE];
 
 char *env_name_spec = "EEPROM";
 int env_eeprom_bus = -1;
@@ -111,7 +112,7 @@ uchar env_get_char_spec(int index)
 
 void env_relocate_spec(void)
 {
-	char buf[CONFIG_ENV_SIZE];
+	char *buf = env_buf;
 	unsigned int off = CONFIG_ENV_OFFSET;
 
 #ifdef CONFIG_ENV_OFFSET_REDUND
@@ -126,7 +127,7 @@ void env_relocate_spec(void)
 
 int saveenv(void)
 {
-	env_t	env_new;
+	env_t	*env_new = (env_t *)env_buf;
 	ssize_t	len;
 	char	*res;
 	int	rc;
@@ -138,13 +139,13 @@ int saveenv(void)
 
 	BUG_ON(env_ptr != NULL);
 
-	res = (char *)&env_new.data;
+	res = (char *)env_new->data;
 	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
 	if (len < 0) {
 		error("Cannot export environment: errno = %d\n", errno);
 		return 1;
 	}
-	env_new.crc = crc32(0, env_new.data, ENV_SIZE);
+	env_new->crc = crc32(0, env_new->data, ENV_SIZE);
 
 #ifdef CONFIG_ENV_OFFSET_REDUND
 	if (gd->env_valid == 1) {
@@ -152,11 +153,11 @@ int saveenv(void)
 		off_red	= CONFIG_ENV_OFFSET;
 	}
 
-	env_new.flags = ACTIVE_FLAG;
+	env_new->flags = ACTIVE_FLAG;
 #endif
 
 	rc = eeprom_bus_write(CONFIG_SYS_DEF_EEPROM_ADDR,
-			      off, (uchar *)&env_new, CONFIG_ENV_SIZE);
+			      off, (uchar *)env_new, CONFIG_ENV_SIZE);
 
 #ifdef CONFIG_ENV_OFFSET_REDUND
 	if (rc == 0) {

+ 6 - 5
common/env_fat.c

@@ -37,6 +37,7 @@
 char *env_name_spec = "FAT";
 
 env_t *env_ptr;
+static char env_buf[CONFIG_ENV_SIZE];
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -52,7 +53,7 @@ int env_init(void)
 #ifdef CONFIG_CMD_SAVEENV
 int saveenv(void)
 {
-	env_t	env_new;
+	env_t	*env_new = env_buf;
 	ssize_t	len;
 	char	*res;
 	block_dev_desc_t *dev_desc = NULL;
@@ -60,7 +61,7 @@ int saveenv(void)
 	int part = FAT_ENV_PART;
 	int err;
 
-	res = (char *)&env_new.data;
+	res = (char *)env_new->data;
 	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
 	if (len < 0) {
 		error("Cannot export environment: errno = %d\n", errno);
@@ -95,8 +96,8 @@ int saveenv(void)
 		return 1;
 	}
 
-	env_new.crc = crc32(0, env_new.data, ENV_SIZE);
-	err = file_fat_write(FAT_ENV_FILE, (void *)&env_new, sizeof(env_t));
+	env_new->crc = crc32(0, env_new->data, ENV_SIZE);
+	err = file_fat_write(FAT_ENV_FILE, (void *)env_new, sizeof(env_t));
 	if (err == -1) {
 		printf("\n** Unable to write \"%s\" from %s%d:%d **\n",
 			FAT_ENV_FILE, FAT_ENV_INTERFACE, dev, part);
@@ -110,7 +111,7 @@ int saveenv(void)
 
 void env_relocate_spec(void)
 {
-	char buf[CONFIG_ENV_SIZE];
+	char *buf = env_buf;
 	block_dev_desc_t *dev_desc = NULL;
 	int dev = FAT_ENV_DEVICE;
 	int part = FAT_ENV_PART;

+ 7 - 6
common/env_mmc.c

@@ -40,6 +40,8 @@ env_t *env_ptr = &environment;
 env_t *env_ptr;
 #endif /* ENV_IS_EMBEDDED */
 
+DEFINE_CACHE_ALIGN_BUFFER(char, env_buf, CONFIG_ENV_SIZE);
+
 DECLARE_GLOBAL_DATA_PTR;
 
 #if !defined(CONFIG_ENV_OFFSET)
@@ -112,7 +114,7 @@ static inline int write_env(struct mmc *mmc, unsigned long size,
 
 int saveenv(void)
 {
-	ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1);
+	env_t *env_new = (env_t *)env_buf;
 	ssize_t	len;
 	char	*res;
 	struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
@@ -127,7 +129,7 @@ int saveenv(void)
 		goto fini;
 	}
 
-	res = (char *)&env_new->data;
+	res = (char *)env_new->data;
 	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
 	if (len < 0) {
 		error("Cannot export environment: errno = %d\n", errno);
@@ -135,7 +137,7 @@ int saveenv(void)
 		goto fini;
 	}
 
-	env_new->crc = crc32(0, &env_new->data[0], ENV_SIZE);
+	env_new->crc = crc32(0, env_new->data, ENV_SIZE);
 	printf("Writing to MMC(%d)... ", CONFIG_SYS_MMC_ENV_DEV);
 	if (write_env(mmc, CONFIG_ENV_SIZE, offset, (u_char *)env_new)) {
 		puts("failed\n");
@@ -169,7 +171,6 @@ static inline int read_env(struct mmc *mmc, unsigned long size,
 void env_relocate_spec(void)
 {
 #if !defined(ENV_IS_EMBEDDED)
-	ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE);
 	struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
 	u32 offset;
 	int ret;
@@ -184,12 +185,12 @@ void env_relocate_spec(void)
 		goto fini;
 	}
 
-	if (read_env(mmc, CONFIG_ENV_SIZE, offset, buf)) {
+	if (read_env(mmc, CONFIG_ENV_SIZE, offset, env_buf)) {
 		ret = 1;
 		goto fini;
 	}
 
-	env_import(buf, 1);
+	env_import(env_buf, 1);
 	ret = 0;
 
 fini:

+ 12 - 11
common/env_nand.c

@@ -64,6 +64,8 @@ env_t *env_ptr = (env_t *)CONFIG_NAND_ENV_DST;
 env_t *env_ptr;
 #endif /* ENV_IS_EMBEDDED */
 
+DEFINE_CACHE_ALIGN_BUFFER(char, env_buf, CONFIG_ENV_SIZE);
+
 DECLARE_GLOBAL_DATA_PTR;
 
 /*
@@ -173,7 +175,7 @@ static unsigned char env_flags;
 
 int saveenv(void)
 {
-	env_t	env_new;
+	env_t	*env_new = (env_t *)env_buf;
 	ssize_t	len;
 	char	*res;
 	int	ret = 0;
@@ -185,14 +187,14 @@ int saveenv(void)
 	if (CONFIG_ENV_RANGE < CONFIG_ENV_SIZE)
 		return 1;
 
-	res = (char *)&env_new.data;
+	res = (char *)env_new->data;
 	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
 	if (len < 0) {
 		error("Cannot export environment: errno = %d\n", errno);
 		return 1;
 	}
-	env_new.crc	= crc32(0, env_new.data, ENV_SIZE);
-	env_new.flags	= ++env_flags; /* increase the serial */
+	env_new->crc	= crc32(0, env_new->data, ENV_SIZE);
+	env_new->flags	= ++env_flags; /* increase the serial */
 
 	if (gd->env_valid == 1) {
 		puts("Erasing redundant NAND...\n");
@@ -201,7 +203,7 @@ int saveenv(void)
 			return 1;
 
 		puts("Writing to redundant NAND... ");
-		ret = writeenv(CONFIG_ENV_OFFSET_REDUND, (u_char *)&env_new);
+		ret = writeenv(CONFIG_ENV_OFFSET_REDUND, (u_char *)env_new);
 	} else {
 		puts("Erasing NAND...\n");
 		nand_erase_options.offset = CONFIG_ENV_OFFSET;
@@ -209,7 +211,7 @@ int saveenv(void)
 			return 1;
 
 		puts("Writing to NAND... ");
-		ret = writeenv(CONFIG_ENV_OFFSET, (u_char *)&env_new);
+		ret = writeenv(CONFIG_ENV_OFFSET, (u_char *)env_new);
 	}
 	if (ret) {
 		puts("FAILED!\n");
@@ -226,7 +228,7 @@ int saveenv(void)
 int saveenv(void)
 {
 	int	ret = 0;
-	ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1);
+	env_t	*env_new = (env_t *)env_buf;
 	ssize_t	len;
 	char	*res;
 	nand_erase_options_t nand_erase_options;
@@ -238,7 +240,7 @@ int saveenv(void)
 	if (CONFIG_ENV_RANGE < CONFIG_ENV_SIZE)
 		return 1;
 
-	res = (char *)&env_new->data;
+	res = (char *)env_new->data;
 	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
 	if (len < 0) {
 		error("Cannot export environment: errno = %d\n", errno);
@@ -404,7 +406,6 @@ void env_relocate_spec(void)
 {
 #if !defined(ENV_IS_EMBEDDED)
 	int ret;
-	ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE);
 
 #if defined(CONFIG_ENV_OFFSET_OOB)
 	ret = get_nand_env_oob(&nand_info[0], &nand_env_oob_offset);
@@ -420,13 +421,13 @@ void env_relocate_spec(void)
 	}
 #endif
 
-	ret = readenv(CONFIG_ENV_OFFSET, (u_char *)buf);
+	ret = readenv(CONFIG_ENV_OFFSET, (u_char *)env_buf);
 	if (ret) {
 		set_default_env("!readenv() failed");
 		return;
 	}
 
-	env_import(buf, 1);
+	env_import(env_buf, 1);
 #endif /* ! ENV_IS_EMBEDDED */
 }
 #endif /* CONFIG_ENV_OFFSET_REDUND */

+ 16 - 10
common/env_nvram.c

@@ -59,6 +59,10 @@ env_t *env_ptr = (env_t *)CONFIG_ENV_ADDR;
 
 char *env_name_spec = "NVRAM";
 
+#ifdef CONFIG_SYS_NVRAM_ACCESS_ROUTINE
+static char env_buf[CONFIG_ENV_SIZE];
+#endif
+
 #ifdef CONFIG_SYS_NVRAM_ACCESS_ROUTINE
 uchar env_get_char_spec(int index)
 {
@@ -72,36 +76,38 @@ uchar env_get_char_spec(int index)
 
 void env_relocate_spec(void)
 {
-	char buf[CONFIG_ENV_SIZE];
+	char *buf;
 
 #if defined(CONFIG_SYS_NVRAM_ACCESS_ROUTINE)
+	buf = env_buf;
 	nvram_read(buf, CONFIG_ENV_ADDR, CONFIG_ENV_SIZE);
 #else
-	memcpy(buf, (void *)CONFIG_ENV_ADDR, CONFIG_ENV_SIZE);
+	buf = (void *)CONFIG_ENV_ADDR;
 #endif
 	env_import(buf, 1);
 }
 
 int saveenv(void)
 {
-	env_t	env_new;
+#ifdef CONFIG_SYS_NVRAM_ACCESS_ROUTINE
+	env_t	*env_new = (env_t *)env_buf;
+#else
+	env_t	*env_new = (env_t *)CONFIG_ENV_ADDR;
+#endif
 	ssize_t	len;
 	char	*res;
 	int	rcode = 0;
 
-	res = (char *)&env_new.data;
+	res = (char *)env_new->data;
 	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
 	if (len < 0) {
 		error("Cannot export environment: errno = %d\n", errno);
 		return 1;
 	}
-	env_new.crc = crc32(0, env_new.data, ENV_SIZE);
+	env_new->crc = crc32(0, env_new->data, ENV_SIZE);
 
 #ifdef CONFIG_SYS_NVRAM_ACCESS_ROUTINE
-	nvram_write(CONFIG_ENV_ADDR, &env_new, CONFIG_ENV_SIZE);
-#else
-	if (memcpy((char *)CONFIG_ENV_ADDR, &env_new, CONFIG_ENV_SIZE) == NULL)
-		rcode = 1;
+	nvram_write(CONFIG_ENV_ADDR, env_new, CONFIG_ENV_SIZE);
 #endif
 	return rcode;
 }
@@ -115,7 +121,7 @@ int env_init(void)
 {
 #if defined(CONFIG_SYS_NVRAM_ACCESS_ROUTINE)
 	ulong crc;
-	uchar data[ENV_SIZE];
+	uchar *data = env_buf;
 
 	nvram_read(&crc, CONFIG_ENV_ADDR, sizeof(ulong));
 	nvram_read(data, CONFIG_ENV_ADDR + sizeof(ulong), ENV_SIZE);

+ 7 - 6
common/env_onenand.c

@@ -42,6 +42,8 @@ char *env_name_spec = "OneNAND";
 #define ONENAND_MAX_ENV_SIZE	CONFIG_ENV_SIZE
 #define ONENAND_ENV_SIZE(mtd)	(ONENAND_MAX_ENV_SIZE - ENV_HEADER_SIZE)
 
+static char env_buf[CONFIG_ENV_SIZE];
+
 DECLARE_GLOBAL_DATA_PTR;
 
 void env_relocate_spec(void)
@@ -56,8 +58,7 @@ void env_relocate_spec(void)
 	char *buf = (char *)&environment;
 #else
 	loff_t env_addr = CONFIG_ENV_ADDR;
-	char onenand_env[ONENAND_MAX_ENV_SIZE];
-	char *buf = (char *)&onenand_env[0];
+	char *buf = env_buf;
 #endif /* ENV_IS_EMBEDDED */
 
 #ifndef ENV_IS_EMBEDDED
@@ -81,7 +82,7 @@ void env_relocate_spec(void)
 
 int saveenv(void)
 {
-	env_t	env_new;
+	env_t	*env_new = env_buf;
 	ssize_t	len;
 	char	*res;
 	struct mtd_info *mtd = &onenand_mtd;
@@ -94,13 +95,13 @@ int saveenv(void)
 		.callback	= NULL,
 	};
 
-	res = (char *)&env_new.data;
+	res = (char *)env_new->data;
 	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
 	if (len < 0) {
 		error("Cannot export environment: errno = %d\n", errno);
 		return 1;
 	}
-	env_new.crc = crc32(0, env_new.data, ENV_SIZE);
+	env_new->crc = crc32(0, env_new->data, ENV_SIZE);
 
 	instr.len = CONFIG_ENV_SIZE;
 #ifdef CONFIG_ENV_ADDR_FLEX
@@ -119,7 +120,7 @@ int saveenv(void)
 	}
 
 	if (mtd->write(mtd, env_addr, ONENAND_MAX_ENV_SIZE, &retlen,
-			(u_char *)&env_new)) {
+			(u_char *)env_new)) {
 		printf("OneNAND: write failed at 0x%llx\n", instr.addr);
 		return 2;
 	}

+ 12 - 11
common/env_sf.c

@@ -58,11 +58,12 @@ DECLARE_GLOBAL_DATA_PTR;
 char *env_name_spec = "SPI Flash";
 
 static struct spi_flash *env_flash;
+static char env_buf[CONFIG_ENV_SIZE];
 
 #if defined(CONFIG_ENV_OFFSET_REDUND)
 int saveenv(void)
 {
-	env_t	env_new;
+	env_t	*env_new = (env_t *)env_buf;
 	ssize_t	len;
 	char	*res, *saved_buffer = NULL, flag = OBSOLETE_FLAG;
 	u32	saved_size, saved_offset, sector = 1;
@@ -78,14 +79,14 @@ int saveenv(void)
 		}
 	}
 
-	res = (char *)&env_new.data;
+	res = (char *)env_new->data;
 	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
 	if (len < 0) {
 		error("Cannot export environment: errno = %d\n", errno);
 		return 1;
 	}
-	env_new.crc	= crc32(0, env_new.data, ENV_SIZE);
-	env_new.flags	= ACTIVE_FLAG;
+	env_new->crc	= crc32(0, env_new->data, ENV_SIZE);
+	env_new->flags	= ACTIVE_FLAG;
 
 	if (gd->env_valid == 1) {
 		env_new_offset = CONFIG_ENV_OFFSET_REDUND;
@@ -125,7 +126,7 @@ int saveenv(void)
 	puts("Writing to SPI flash...");
 
 	ret = spi_flash_write(env_flash, env_new_offset,
-		CONFIG_ENV_SIZE, &env_new);
+		CONFIG_ENV_SIZE, env_new);
 	if (ret)
 		goto done;
 
@@ -137,7 +138,7 @@ int saveenv(void)
 	}
 
 	ret = spi_flash_write(env_flash, env_offset + offsetof(env_t, flags),
-				sizeof(env_new.flags), &flag);
+				sizeof(env_new->flags), &flag);
 	if (ret)
 		goto done;
 
@@ -243,7 +244,7 @@ int saveenv(void)
 	u32	saved_size, saved_offset, sector = 1;
 	char	*res, *saved_buffer = NULL;
 	int	ret = 1;
-	env_t	env_new;
+	env_t	*env_new = (env_t *)env_buf;
 	ssize_t	len;
 
 	if (!env_flash) {
@@ -276,13 +277,13 @@ int saveenv(void)
 			sector++;
 	}
 
-	res = (char *)&env_new.data;
+	res = (char *)env_new->data;
 	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
 	if (len < 0) {
 		error("Cannot export environment: errno = %d\n", errno);
 		goto done;
 	}
-	env_new.crc = crc32(0, env_new.data, ENV_SIZE);
+	env_new->crc = crc32(0, env_new->data, ENV_SIZE);
 
 	puts("Erasing SPI flash...");
 	ret = spi_flash_erase(env_flash, CONFIG_ENV_OFFSET,
@@ -292,7 +293,7 @@ int saveenv(void)
 
 	puts("Writing to SPI flash...");
 	ret = spi_flash_write(env_flash, CONFIG_ENV_OFFSET,
-		CONFIG_ENV_SIZE, &env_new);
+		CONFIG_ENV_SIZE, env_new);
 	if (ret)
 		goto done;
 
@@ -315,7 +316,7 @@ int saveenv(void)
 
 void env_relocate_spec(void)
 {
-	char buf[CONFIG_ENV_SIZE];
+	char *buf = env_buf;
 	int ret;
 
 	env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,