diff options
author | Adrian Hunter <ext-adrian.hunter@nokia.com> | 2007-01-31 10:58:29 -0500 |
---|---|---|
committer | David Woodhouse <dwmw2@infradead.org> | 2007-02-09 10:02:40 -0500 |
commit | 0373615579c7359dfd0bc66139c2e7bf67793480 (patch) | |
tree | c1d110a6abfd5bdbf11ac4bd126c30b8fa93dbd0 /drivers/mtd | |
parent | cfa72397cf3a15f2841447440fd53980b3ecd624 (diff) |
[MTD] [NAND] Correctly validate out-of-band offset and length
Add checks to ensure that out-of-band reads and writes are
not attempted with an invalid offset or length. Specifically,
the offset must be less than the size of oob for a page
and the length must not go beyond the size of the device.
Additionally the checks must adjust for auto-placement
(MTD_OOB_AUTO) of oob data.
Signed-off-by: Adrian Hunter <ext-adrian.hunter@nokia.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 46 |
1 files changed, 41 insertions, 5 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index dfe56e03e48b..c13d66426360 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -1272,10 +1272,25 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, | |||
1272 | DEBUG(MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08Lx, len = %i\n", | 1272 | DEBUG(MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08Lx, len = %i\n", |
1273 | (unsigned long long)from, readlen); | 1273 | (unsigned long long)from, readlen); |
1274 | 1274 | ||
1275 | if (ops->mode == MTD_OOB_RAW) | 1275 | if (ops->mode == MTD_OOB_AUTO) |
1276 | len = mtd->oobsize; | ||
1277 | else | ||
1278 | len = chip->ecc.layout->oobavail; | 1276 | len = chip->ecc.layout->oobavail; |
1277 | else | ||
1278 | len = mtd->oobsize; | ||
1279 | |||
1280 | if (unlikely(ops->ooboffs >= len)) { | ||
1281 | DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: " | ||
1282 | "Attempt to start read outside oob\n"); | ||
1283 | return -EINVAL; | ||
1284 | } | ||
1285 | |||
1286 | /* Do not allow reads past end of device */ | ||
1287 | if (unlikely(from >= mtd->size || | ||
1288 | ops->ooboffs + readlen > ((mtd->size >> chip->page_shift) - | ||
1289 | (from >> chip->page_shift)) * len)) { | ||
1290 | DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: " | ||
1291 | "Attempt read beyond end of device\n"); | ||
1292 | return -EINVAL; | ||
1293 | } | ||
1279 | 1294 | ||
1280 | chipnr = (int)(from >> chip->chip_shift); | 1295 | chipnr = (int)(from >> chip->chip_shift); |
1281 | chip->select_chip(mtd, chipnr); | 1296 | chip->select_chip(mtd, chipnr); |
@@ -1742,19 +1757,40 @@ static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
1742 | static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, | 1757 | static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, |
1743 | struct mtd_oob_ops *ops) | 1758 | struct mtd_oob_ops *ops) |
1744 | { | 1759 | { |
1745 | int chipnr, page, status; | 1760 | int chipnr, page, status, len; |
1746 | struct nand_chip *chip = mtd->priv; | 1761 | struct nand_chip *chip = mtd->priv; |
1747 | 1762 | ||
1748 | DEBUG(MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n", | 1763 | DEBUG(MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n", |
1749 | (unsigned int)to, (int)ops->ooblen); | 1764 | (unsigned int)to, (int)ops->ooblen); |
1750 | 1765 | ||
1766 | if (ops->mode == MTD_OOB_AUTO) | ||
1767 | len = chip->ecc.layout->oobavail; | ||
1768 | else | ||
1769 | len = mtd->oobsize; | ||
1770 | |||
1751 | /* Do not allow write past end of page */ | 1771 | /* Do not allow write past end of page */ |
1752 | if ((ops->ooboffs + ops->ooblen) > mtd->oobsize) { | 1772 | if ((ops->ooboffs + ops->ooblen) > len) { |
1753 | DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: " | 1773 | DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: " |
1754 | "Attempt to write past end of page\n"); | 1774 | "Attempt to write past end of page\n"); |
1755 | return -EINVAL; | 1775 | return -EINVAL; |
1756 | } | 1776 | } |
1757 | 1777 | ||
1778 | if (unlikely(ops->ooboffs >= len)) { | ||
1779 | DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: " | ||
1780 | "Attempt to start write outside oob\n"); | ||
1781 | return -EINVAL; | ||
1782 | } | ||
1783 | |||
1784 | /* Do not allow reads past end of device */ | ||
1785 | if (unlikely(to >= mtd->size || | ||
1786 | ops->ooboffs + ops->ooblen > | ||
1787 | ((mtd->size >> chip->page_shift) - | ||
1788 | (to >> chip->page_shift)) * len)) { | ||
1789 | DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: " | ||
1790 | "Attempt write beyond end of device\n"); | ||
1791 | return -EINVAL; | ||
1792 | } | ||
1793 | |||
1758 | chipnr = (int)(to >> chip->chip_shift); | 1794 | chipnr = (int)(to >> chip->chip_shift); |
1759 | chip->select_chip(mtd, chipnr); | 1795 | chip->select_chip(mtd, chipnr); |
1760 | 1796 | ||