summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mtd/core.c22
-rw-r--r--include/linux/mtd/mtd.h2
2 files changed, 24 insertions, 0 deletions
diff --git a/drivers/mtd/core.c b/drivers/mtd/core.c
index e35571dc3d..161c6ad874 100644
--- a/drivers/mtd/core.c
+++ b/drivers/mtd/core.c
@@ -326,6 +326,11 @@ int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
int ret_code;
*retlen = 0;
+ if (from < 0 || from >= mtd->size || len > mtd->size - from)
+ return -EINVAL;
+ if (!len)
+ return 0;
+
/*
* In the absence of an error, drivers return a non-negative integer
* representing the maximum number of bitflips that were corrected on
@@ -344,11 +349,28 @@ int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
{
*retlen = 0;
+ if (to < 0 || to >= mtd->size || len > mtd->size - to)
+ return -EINVAL;
+ if (!mtd->write || !(mtd->flags & MTD_WRITEABLE))
+ return -EROFS;
+ if (!len)
+ return 0;
+
return mtd->write(mtd, to, len, retlen, buf);
}
int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
{
+ if (instr->addr >= mtd->size || instr->len > mtd->size - instr->addr)
+ return -EINVAL;
+ if (!(mtd->flags & MTD_WRITEABLE))
+ return -EROFS;
+ instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
+ if (!instr->len) {
+ instr->state = MTD_ERASE_DONE;
+ mtd_erase_callback(instr);
+ return 0;
+ }
return mtd->erase(mtd, instr);
}
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index e430217097..421a941aad 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -26,6 +26,8 @@
#define MTD_ERASE_DONE 0x08
#define MTD_ERASE_FAILED 0x10
+#define MTD_FAIL_ADDR_UNKNOWN -1LL
+
/* If the erase fails, fail_addr might indicate exactly which block failed. If
fail_addr = 0xffffffff, the failure was not at the device level or was not
specific to any particular block. */