JFFS2: fix the reading address over nand's limit
authorWagner Popov dos Santos <wpopov@gmail.com>
Tue, 23 Feb 2021 02:30:58 +0000 (23:30 -0300)
committerTom Rini <trini@konsulko.com>
Wed, 7 Apr 2021 14:22:22 +0000 (10:22 -0400)
Fixes address violation in functions read_nand_cached() and
read_onenand_cached(). This happens because these functions
try to read a fixed amount
of data even when the offset+length
is above the nand's limit.

Signed-off-by: Wagner Popov dos Santos <wpopov@gmail.com>
fs/jffs2/jffs2_1pass.c

index a98745c..b399436 100644 (file)
@@ -180,6 +180,7 @@ static int read_nand_cached(u32 off, u32 size, u_char *buf)
        struct mtd_info *mtd;
        u32 bytes_read = 0;
        size_t retlen;
+       size_t toread;
        int cpy_bytes;
 
        mtd = get_nand_dev_by_index(id->num);
@@ -187,8 +188,12 @@ static int read_nand_cached(u32 off, u32 size, u_char *buf)
                return -1;
 
        while (bytes_read < size) {
+               retlen = NAND_CACHE_SIZE;
+               if( nand_cache_off + retlen > mtd->size )
+                       retlen = mtd->size - nand_cache_off;
+
                if ((off + bytes_read < nand_cache_off) ||
-                   (off + bytes_read >= nand_cache_off+NAND_CACHE_SIZE)) {
+                   (off + bytes_read >= nand_cache_off + retlen)) {
                        nand_cache_off = (off + bytes_read) & NAND_PAGE_MASK;
                        if (!nand_cache) {
                                /* This memory never gets freed but 'cause
@@ -201,16 +206,20 @@ static int read_nand_cached(u32 off, u32 size, u_char *buf)
                                }
                        }
 
-                       retlen = NAND_CACHE_SIZE;
+                       toread = NAND_CACHE_SIZE;
+                       if( nand_cache_off + toread > mtd->size )
+                               toread = mtd->size - nand_cache_off;
+
+                       retlen = toread;
                        if (nand_read(mtd, nand_cache_off,
                                      &retlen, nand_cache) < 0 ||
-                                       retlen != NAND_CACHE_SIZE) {
+                                       retlen != toread) {
                                printf("read_nand_cached: error reading nand off %#x size %d bytes\n",
-                                               nand_cache_off, NAND_CACHE_SIZE);
+                                               nand_cache_off, toread);
                                return -1;
                        }
                }
-               cpy_bytes = nand_cache_off + NAND_CACHE_SIZE - (off + bytes_read);
+               cpy_bytes = nand_cache_off + retlen - (off + bytes_read);
                if (cpy_bytes > size - bytes_read)
                        cpy_bytes = size - bytes_read;
                memcpy(buf + bytes_read,
@@ -283,11 +292,16 @@ static int read_onenand_cached(u32 off, u32 size, u_char *buf)
 {
        u32 bytes_read = 0;
        size_t retlen;
+       size_t toread;
        int cpy_bytes;
 
        while (bytes_read < size) {
+               retlen = ONENAND_CACHE_SIZE;
+               if( onenand_cache_off + retlen > onenand_mtd.size )
+                       retlen = onenand_mtd.size - onenand_cache_off;
+
                if ((off + bytes_read < onenand_cache_off) ||
-                   (off + bytes_read >= onenand_cache_off + ONENAND_CACHE_SIZE)) {
+                   (off + bytes_read >= onenand_cache_off + retlen)) {
                        onenand_cache_off = (off + bytes_read) & ONENAND_PAGE_MASK;
                        if (!onenand_cache) {
                                /* This memory never gets freed but 'cause
@@ -300,16 +314,19 @@ static int read_onenand_cached(u32 off, u32 size, u_char *buf)
                                }
                        }
 
-                       retlen = ONENAND_CACHE_SIZE;
+                       toread = ONENAND_CACHE_SIZE;
+                       if( onenand_cache_off + toread > onenand_mtd.size )
+                               toread = onenand_mtd.size - onenand_cache_off;
+                       retlen = toread;
                        if (onenand_read(&onenand_mtd, onenand_cache_off, retlen,
                                                &retlen, onenand_cache) < 0 ||
-                                       retlen != ONENAND_CACHE_SIZE) {
+                                       retlen != toread) {
                                printf("read_onenand_cached: error reading nand off %#x size %d bytes\n",
-                                       onenand_cache_off, ONENAND_CACHE_SIZE);
+                                       onenand_cache_off, toread);
                                return -1;
                        }
                }
-               cpy_bytes = onenand_cache_off + ONENAND_CACHE_SIZE - (off + bytes_read);
+               cpy_bytes = onenand_cache_off + retlen - (off + bytes_read);
                if (cpy_bytes > size - bytes_read)
                        cpy_bytes = size - bytes_read;
                memcpy(buf + bytes_read,