summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2015-02-05 10:37:48 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2015-02-10 09:55:44 +0100
commit3b71b23b46278de78f3db265ea90a28c8e4246a5 (patch)
treed5cffdee7651f86dcb600ac1f66a695761dead21
parent9d82489c07872ba35aa5ca441633869ce5bf1058 (diff)
downloadbarebox-3b71b23b46278de78f3db265ea90a28c8e4246a5.tar.gz
barebox-3b71b23b46278de78f3db265ea90a28c8e4246a5.tar.xz
mtd: nand-bb: Fix accesses beyond device
When a block is marked bad after the bb device has been created the real size of the bb device is smaller than the calculated size on creation. In this case we can't rely on the upper layers anymore that they won't pass read/write sizes in that fit into the device. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r--drivers/mtd/nand/nand-bb.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/drivers/mtd/nand/nand-bb.c b/drivers/mtd/nand/nand-bb.c
index d888f903e0..e38517d983 100644
--- a/drivers/mtd/nand/nand-bb.c
+++ b/drivers/mtd/nand/nand-bb.c
@@ -57,6 +57,11 @@ static ssize_t nand_bb_read(struct cdev *cdev, void *buf, size_t count,
debug("%s 0x%08llx %d\n", __func__, offset, count);
while (count) {
+ loff_t max = bb->mtd->size - bb->offset;
+
+ if (max <= 0)
+ break;
+
if (mtd_block_isbad(bb->mtd, offset)) {
printf("skipping bad block at 0x%08llx\n", bb->offset);
bb->offset += bb->mtd->erasesize;
@@ -66,6 +71,9 @@ static ssize_t nand_bb_read(struct cdev *cdev, void *buf, size_t count,
now = min(count, (size_t)(bb->mtd->erasesize -
((size_t)bb->offset % bb->mtd->erasesize)));
+ if (now > max)
+ now = max;
+
ret = mtd_read(bb->mtd, bb->offset, now, &retlen, buf);
if (ret < 0)
return ret;
@@ -90,6 +98,11 @@ static int nand_bb_write_buf(struct nand_bb *bb, size_t count)
loff_t cur_ofs = bb->offset & ~(BB_WRITEBUF_SIZE - 1);
while (count) {
+ loff_t max = bb->mtd->size - bb->offset;
+
+ if (max <= 0)
+ return -ENOSPC;
+
if (mtd_block_isbad(bb->mtd, cur_ofs)) {
debug("skipping bad block at 0x%08llx\n", cur_ofs);
bb->offset += bb->mtd->erasesize;
@@ -98,6 +111,9 @@ static int nand_bb_write_buf(struct nand_bb *bb, size_t count)
}
now = min(count, (size_t)(bb->mtd->erasesize));
+ if (now > max)
+ return -ENOSPC;
+
ret = mtd_write(bb->mtd, cur_ofs, now, &retlen, buf);
if (ret < 0)
return ret;