summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWagner Popov dos Santos <wpopov@gmail.com>2021-02-22 23:30:58 -0300
committerTom Rini <trini@konsulko.com>2021-04-07 10:22:22 -0400
commit610a2cc7a38782bf2fa5c1037959a42838ebb2ad (patch)
tree5a6b392ffa848995cd93ddb73f195c4ac3fc7f97
parent02395fec007657c5beb4f7fd77784e10b3054c90 (diff)
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 <wpopov@gmail.com>
-rw-r--r--fs/jffs2/jffs2_1pass.c37
1 files 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,