nvram: fix memory leak
[openwrt/openwrt.git] / package / utils / nvram / src / nvram.c
index 605b4e114177e592fef8748ee9b565d5a18ab109..ca893921076ee17db3e855138f91c28a87d2d1c4 100644 (file)
@@ -65,7 +65,7 @@ static void _nvram_free(nvram_handle_t *h)
 static nvram_tuple_t * _nvram_realloc( nvram_handle_t *h, nvram_tuple_t *t,
        const char *name, const char *value )
 {
-       if ((strlen(value) + 1) > NVRAM_SPACE)
+       if ((strlen(value) + 1) > h->length - h->offset)
                return NULL;
 
        if (!t) {
@@ -286,11 +286,11 @@ int nvram_commit(nvram_handle_t *h)
 
        /* Clear data area */
        ptr = (char *) header + sizeof(nvram_header_t);
-       memset(ptr, 0xFF, NVRAM_SPACE - sizeof(nvram_header_t));
+       memset(ptr, 0xFF, nvram_part_size - h->offset - sizeof(nvram_header_t));
        memset(&tmp, 0, sizeof(nvram_header_t));
 
        /* Leave space for a double NUL at the end */
-       end = (char *) header + NVRAM_SPACE - 2;
+       end = (char *) header + nvram_part_size - h->offset - 2;
 
        /* Write out all tuples */
        for (i = 0; i < NVRAM_ARRAYSIZE(h->nvram_hash); i++) {
@@ -364,7 +364,12 @@ nvram_handle_t * nvram_open(const char *file, int rdonly)
 
                if( mmap_area != MAP_FAILED )
                {
-                       for( i = 0; i <= ((nvram_part_size - NVRAM_SPACE) / sizeof(uint32_t)); i++ )
+                       /*
+                        * Start looking for NVRAM_MAGIC at beginning of MTD
+                        * partition. Stop if there is less than NVRAM_MIN_SPACE
+                        * to check, that was the lowest used size.
+                        */
+                       for( i = 0; i <= ((nvram_part_size - NVRAM_MIN_SPACE) / sizeof(uint32_t)); i++ )
                        {
                                if( ((uint32_t *)mmap_area)[i] == NVRAM_MAGIC )
                                {
@@ -375,7 +380,9 @@ nvram_handle_t * nvram_open(const char *file, int rdonly)
 
                        if( offset < 0 )
                        {
+                               munmap(mmap_area, nvram_part_size);
                                free(mtd);
+                               close(fd);
                                return NULL;
                        }
                        else if( (h = malloc(sizeof(nvram_handle_t))) != NULL )
@@ -389,8 +396,8 @@ nvram_handle_t * nvram_open(const char *file, int rdonly)
 
                                header = nvram_header(h);
 
-                               if( header->magic == NVRAM_MAGIC )
-                               {
+                               if (header->magic == NVRAM_MAGIC &&
+                                   (rdonly || header->len < h->length - h->offset)) {
                                        _nvram_rehash(h);
                                        free(mtd);
                                        return h;
@@ -405,6 +412,7 @@ nvram_handle_t * nvram_open(const char *file, int rdonly)
        }
 
        free(mtd);
+       close(fd);
        return NULL;
 }
 
@@ -427,18 +435,8 @@ char * nvram_find_mtd(void)
        char dev[PATH_MAX];
        char *path = NULL;
        struct stat s;
-       int supported = 1;
-
-       /* Refuse any operation on the WGT634U */
-       if( (fp = fopen("/proc/diag/model", "r")) )
-       {
-               if( fgets(dev, sizeof(dev), fp) && !strncmp(dev, "Netgear WGT634U", 15) )
-                       supported = 0;
-
-               fclose(fp);
-       }
 
-       if( supported && (fp = fopen("/proc/mtd", "r")) )
+       if ((fp = fopen("/proc/mtd", "r")))
        {
                while( fgets(dev, sizeof(dev), fp) )
                {