env: fix potential stack overflow in environment functions
authorRob Herring <rob.herring@calxeda.com>
Fri, 22 Mar 2013 11:26:21 +0000 (11:26 +0000)
committerTom Rini <trini@ti.com>
Tue, 2 Apr 2013 20:23:34 +0000 (16:23 -0400)
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>
common/env_dataflash.c
common/env_eeprom.c
common/env_fat.c
common/env_mmc.c
common/env_nand.c
common/env_nvram.c
common/env_onenand.c
common/env_sf.c

index 38c96157b9fa66a41c53c6722cbab2127565c84e..0591b999ad63e7a810d432241283c3bf26e52684 100644 (file)
@@ -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);
 }
 
index 45c935b6df7895844ae9914e01b69ffe6fa2333e..b136f04ebe1bb17dafbad0cf44bfb9a9593e138c 100644 (file)
@@ -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) {
index c0f18ab97dfde66b32a8a8cb7fe7437fcdfa3410..dd7139d4deca9b473415bc00a8ad6c24d829a2e2 100644 (file)
@@ -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;
index 02bd5aed10cfeee50842cee00f9895050264c814..f5680134b22c2e356e188c9b8320cc334f5c8dd0 100644 (file)
@@ -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:
index 5b69889c02a70fc7f167eab7a04864ac3a2ebdfc..8cc2055eb366c6b5bf0d5d3f0dd6df589462f454 100644 (file)
@@ -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 */
index eab0e7be0ecb90bc11f842dbe521e3df3c60f9dc..ff74a6c2c65e6c7127e4042f97da9263f482a502 100644 (file)
@@ -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);
index faa903d2f0251cd2459daef22d6d6514124dc86c..6fd5613eebef0dfa1a607f16848fabe92ead28af 100644 (file)
@@ -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;
        }
index d9e9085461bb6759b0b0ee0cc2f717d6653ede99..9a592ba9560c787ccba064b5583b386bb9e6cea6 100644 (file)
@@ -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,