From 610a2cc7a38782bf2fa5c1037959a42838ebb2ad Mon Sep 17 00:00:00 2001 From: Wagner Popov dos Santos Date: Mon, 22 Feb 2021 23:30:58 -0300 Subject: [PATCH 1/2] JFFS2: fix the reading address over nand's limit 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 --- fs/jffs2/jffs2_1pass.c | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/fs/jffs2/jffs2_1pass.c b/fs/jffs2/jffs2_1pass.c index a98745c50e..b39943671c 100644 --- a/fs/jffs2/jffs2_1pass.c +++ b/fs/jffs2/jffs2_1pass.c @@ -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, From fc25ffe7d2277ff043f76821452bfc8d05a80bd7 Mon Sep 17 00:00:00 2001 From: Wagner Popov dos Santos Date: Tue, 23 Feb 2021 00:49:00 -0300 Subject: [PATCH 2/2] JFFS2: fix jffs2 summary datacrc status uninitialized The function jffs2_1pass_read_inode() was discarding the summary inodes and dirent because the value in datacrc flag wasn't initialized in function jffs2_sum_process_sum_data(). This fix initializes the status of all summary records to indicate that the CRC needs to be verified when they are loaded. Before this fix, the behaviors produced by the undefined value of datacrc was: - Summary's registries were discarded when 'b->datacrc' is equal as 'CRC_BAD'. - Summary's registries were not checked when b->datacrc differs of 'CRC_BAD' and 'CRC_UNKNOWN' So, almost all of the time the crc just isn't checked, and in some cases the registries are discarded. Signed-off-by: Wagner Popov dos Santos --- fs/jffs2/jffs2_1pass.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/jffs2/jffs2_1pass.c b/fs/jffs2/jffs2_1pass.c index b39943671c..1818e81215 100644 --- a/fs/jffs2/jffs2_1pass.c +++ b/fs/jffs2/jffs2_1pass.c @@ -1293,6 +1293,7 @@ static int jffs2_sum_process_sum_data(struct part_info *part, uint32_t offset, &spi->version); b->ino = sum_get_unaligned32( &spi->inode); + b->datacrc = CRC_UNKNOWN; } sp += JFFS2_SUMMARY_INODE_SIZE; @@ -1314,6 +1315,7 @@ static int jffs2_sum_process_sum_data(struct part_info *part, uint32_t offset, &spd->version); b->pino = sum_get_unaligned32( &spd->pino); + b->datacrc = CRC_UNKNOWN; } sp += JFFS2_SUMMARY_DIRENT_SIZE(