From edcb3b14863e1a6aa1923eeaa81125a00cf51a80 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Thu, 6 Aug 2009 15:18:37 -0700 Subject: [PATCH 1/4] mtd: m25p80: fix null pointer dereference bug This patch fixes the following oops, observed with MTD_PARTITIONS=n: m25p80 spi32766.0: m25p80 (1024 Kbytes) Unable to handle kernel paging request for data at address 0x00000008 Faulting instruction address: 0xc03a54b0 Oops: Kernel access of bad area, sig: 11 [#1] Modules linked in: NIP: c03a54b0 LR: c03a5494 CTR: c01e98b8 REGS: ef82bb60 TRAP: 0300 Not tainted (2.6.31-rc4-00167-g4733fd3) MSR: 00029000 CR: 24022022 XER: 20000000 DEAR: 00000008, ESR: 00000000 TASK = ef82c000[1] 'swapper' THREAD: ef82a000 GPR00: 00000000 ef82bc10 ef82c000 0000002e 00001eb8 ffffffff c01e9824 00000036 GPR08: c054ed40 c0542a08 00001eb8 00004000 22022022 1001a1a0 3ff8fd00 00000000 GPR16: 00000000 00000001 00000000 00000000 ef82bddc c0530000 efbef500 ef8356d0 GPR24: 00000000 ef8356d0 00000000 efbf7a00 c0530ec4 ffffffed efbf5300 c0541f98 NIP [c03a54b0] m25p_probe+0x22c/0x354 LR [c03a5494] m25p_probe+0x210/0x354 Call Trace: [ef82bc10] [c03a5494] m25p_probe+0x210/0x354 (unreliable) [ef82bca0] [c024e37c] spi_drv_probe+0x2c/0x3c [ef82bcb0] [c01f1afc] driver_probe_device+0xa4/0x178 [ef82bcd0] [c01f06e8] bus_for_each_drv+0x6c/0xa8 [ef82bd00] [c01f1a34] device_attach+0x84/0xa8 ... Signed-off-by: Anton Vorontsov Cc: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/devices/m25p80.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index ae5fe91867e1..10ed195c0c1c 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -736,7 +736,7 @@ static int __devinit m25p_probe(struct spi_device *spi) flash->partitioned = 1; return add_mtd_partitions(&flash->mtd, parts, nr_parts); } - } else if (data->nr_parts) + } else if (data && data->nr_parts) dev_warn(&spi->dev, "ignoring %d default partitions on %s\n", data->nr_parts, data->name); From 4149ed1aa944ab864024982a2e568d17eccff504 Mon Sep 17 00:00:00 2001 From: Dimitri Gorokhovik Date: Thu, 3 Sep 2009 14:59:13 +0100 Subject: [PATCH 2/4] mtd: nftl: write support is broken Write support is broken in NFTL. Fix it. Signed-off-by: Cc: Tim Gardner Cc: Scott James Remnant Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse --- drivers/mtd/nftlcore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c index fb86cacd5bdb..665d3eba2f47 100644 --- a/drivers/mtd/nftlcore.c +++ b/drivers/mtd/nftlcore.c @@ -181,7 +181,7 @@ static int nftl_write(struct mtd_info *mtd, loff_t offs, size_t len, int res; ops.mode = MTD_OOB_PLACE; - ops.ooboffs = offs; + ops.ooboffs = offs & (mtd->writesize - 1); ops.ooblen = mtd->oobsize; ops.oobbuf = oob; ops.datbuf = buf; From 16f05c2b68520f94e365f9d347a7076f4ff00ad5 Mon Sep 17 00:00:00 2001 From: Dimitri Gorokhovik Date: Thu, 3 Sep 2009 14:04:22 +0100 Subject: [PATCH 3/4] mtd: nftl: fix offset alignments Arithmetic conversion in the mask computation makes the upper word of the second argument passed down to mtd->read_oob(), be always 0 (assuming 'offs' being a 64-bit signed long long type, and 'mtd->writesize' being a 32-bit unsigned int type). This patch applies over the other one adding masking in nftl_write, "nftl: write support is broken". Signed-off-by: Dimitri Gorokhovik Cc: Tim Gardner Cc: Scott James Remnant Signed-off-by: David Woodhouse --- drivers/mtd/nftlcore.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c index 665d3eba2f47..1002e1882996 100644 --- a/drivers/mtd/nftlcore.c +++ b/drivers/mtd/nftlcore.c @@ -135,16 +135,17 @@ static void nftl_remove_dev(struct mtd_blktrans_dev *dev) int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len, size_t *retlen, uint8_t *buf) { + loff_t mask = mtd->writesize - 1; struct mtd_oob_ops ops; int res; ops.mode = MTD_OOB_PLACE; - ops.ooboffs = offs & (mtd->writesize - 1); + ops.ooboffs = offs & mask; ops.ooblen = len; ops.oobbuf = buf; ops.datbuf = NULL; - res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops); + res = mtd->read_oob(mtd, offs & ~mask, &ops); *retlen = ops.oobretlen; return res; } @@ -155,16 +156,17 @@ int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len, int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len, size_t *retlen, uint8_t *buf) { + loff_t mask = mtd->writesize - 1; struct mtd_oob_ops ops; int res; ops.mode = MTD_OOB_PLACE; - ops.ooboffs = offs & (mtd->writesize - 1); + ops.ooboffs = offs & mask; ops.ooblen = len; ops.oobbuf = buf; ops.datbuf = NULL; - res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops); + res = mtd->write_oob(mtd, offs & ~mask, &ops); *retlen = ops.oobretlen; return res; } @@ -177,17 +179,18 @@ int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len, static int nftl_write(struct mtd_info *mtd, loff_t offs, size_t len, size_t *retlen, uint8_t *buf, uint8_t *oob) { + loff_t mask = mtd->writesize - 1; struct mtd_oob_ops ops; int res; ops.mode = MTD_OOB_PLACE; - ops.ooboffs = offs & (mtd->writesize - 1); + ops.ooboffs = offs & mask; ops.ooblen = mtd->oobsize; ops.oobbuf = oob; ops.datbuf = buf; ops.len = len; - res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops); + res = mtd->write_oob(mtd, offs & ~mask, &ops); *retlen = ops.retlen; return res; } From bc8cec0dff072f1a45ce7f6b2c5234bb3411ac51 Mon Sep 17 00:00:00 2001 From: Massimo Cirillo Date: Thu, 27 Aug 2009 10:44:09 +0200 Subject: [PATCH 4/4] JFFS2: add missing verify buffer allocation/deallocation The function jffs2_nor_wbuf_flash_setup() doesn't allocate the verify buffer if CONFIG_JFFS2_FS_WBUF_VERIFY is defined, so causing a kernel panic when that macro is enabled and the verify function is called. Similarly the jffs2_nor_wbuf_flash_cleanup() must free the buffer if CONFIG_JFFS2_FS_WBUF_VERIFY is enabled. The following patch fixes the problem. The following patch applies to 2.6.30 kernel. Signed-off-by: Massimo Cirillo Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse Cc: stable@kernel.org --- fs/jffs2/wbuf.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index d9a721e6db70..5ef7bac265e5 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -1268,10 +1268,20 @@ int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c) { if (!c->wbuf) return -ENOMEM; +#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY + c->wbuf_verify = kmalloc(c->wbuf_pagesize, GFP_KERNEL); + if (!c->wbuf_verify) { + kfree(c->wbuf); + return -ENOMEM; + } +#endif return 0; } void jffs2_nor_wbuf_flash_cleanup(struct jffs2_sb_info *c) { +#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY + kfree(c->wbuf_verify); +#endif kfree(c->wbuf); }