Skip to content

Commit af5e34a

Browse files
committed
Merge tag 'mtd/fixes-for-7.2-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux
Pull mtd fixes from Miquel Raynal: "Among the most important fixes that we have here, there are: - the revert of the uclinux map driver which was presumed to be no longer used but in fact was - the use of SPI match data to get chip capabilities in the mchp23k256 driver - several fixes addressing the newly introduced virt-concat support - a missing build dependency on ndfc as well as the usual load (if not actually bigger than usual) of uninitialized variables, leaks, double free, and AI fuzzed issues being fixed" * tag 'mtd/fixes-for-7.2-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux: Revert "mtd: maps: remove uclinux map driver" mtd: onenand: samsung: report DMA completion timeouts mtd: rawnand: fsl_ifc: return errors for failed page reads mtd: mchp23k256: use SPI match data for chip caps mtd: rawnand: lpc32xx_slc: fail DMA transfer on completion timeout mtd: rawnand: lpc32xx_mlc: fail DMA transfers on timeout mtd: fix double free and WARN_ON in add_mtd_device() error paths mtd: virt-concat: free duplicate generated name mtd: nand: mtk-ecc: stop on ECC idle timeouts mtd: mtdswap: remove debugfs stats file on teardown mtd: mtdpart: validate partition bounds in mtd_add_partition() mtd: mtdpart: fix uninitialized erasesize on MTDPART_OFS_RETAIN error path mtd: rawnand: ndfc: add CONFIG_OF dependency mtd: spinand: initialize ret in regular page reads mtd: virt_concat: fix use-after-free in mtd_virt_concat_destroy() mtd: rawnand: ingenic: handle ECC clock enable failures mtd: nand: ecc-mtk: handle ECC clock enable failures mtd: virt_concat: fix use-after-free in mtd_virt_concat_destroy_joins() mtd: rawnand: ndfc: fix gcc uninitialized var
2 parents 45419d0 + 2b533e7 commit af5e34a

17 files changed

Lines changed: 224 additions & 23 deletions

File tree

drivers/mtd/devices/mchp23k256.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ static int mchp23k256_probe(struct spi_device *spi)
188188

189189
data = dev_get_platdata(&spi->dev);
190190

191-
flash->caps = of_device_get_match_data(&spi->dev);
191+
flash->caps = spi_get_device_match_data(spi);
192192
if (!flash->caps)
193193
flash->caps = &mchp23k256_caps;
194194

drivers/mtd/maps/Kconfig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,12 @@ config MTD_PCMCIA_ANONYMOUS
277277

278278
If unsure, say N.
279279

280+
config MTD_UCLINUX
281+
bool "Generic uClinux RAM/ROM filesystem support"
282+
depends on (MTD_RAM=y || MTD_ROM=y) && (!MMU || COLDFIRE)
283+
help
284+
Map driver to support image based filesystems for uClinux.
285+
280286
config MTD_PLATRAM
281287
tristate "Map driver for platform device RAM (mtd-ram)"
282288
select MTD_RAM

drivers/mtd/maps/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ obj-$(CONFIG_MTD_SUN_UFLASH) += sun_uflash.o
3030
obj-$(CONFIG_MTD_SCx200_DOCFLASH)+= scx200_docflash.o
3131
obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o
3232
obj-$(CONFIG_MTD_PCI) += pci.o
33+
obj-$(CONFIG_MTD_UCLINUX) += uclinux.o
3334
obj-$(CONFIG_MTD_SCB2_FLASH) += scb2_flash.o
3435
obj-$(CONFIG_MTD_PLATRAM) += plat-ram.o
3536
obj-$(CONFIG_MTD_VMU) += vmu-flash.o

drivers/mtd/maps/uclinux.c

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/****************************************************************************/
2+
3+
/*
4+
* uclinux.c -- generic memory mapped MTD driver for uclinux
5+
*
6+
* (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com)
7+
*
8+
* License: GPL
9+
*/
10+
11+
/****************************************************************************/
12+
13+
#include <linux/moduleparam.h>
14+
#include <linux/types.h>
15+
#include <linux/init.h>
16+
#include <linux/kernel.h>
17+
#include <linux/fs.h>
18+
#include <linux/mm.h>
19+
#include <linux/major.h>
20+
#include <linux/mtd/mtd.h>
21+
#include <linux/mtd/map.h>
22+
#include <linux/mtd/partitions.h>
23+
#include <asm/io.h>
24+
#include <asm/sections.h>
25+
26+
/****************************************************************************/
27+
28+
#ifdef CONFIG_MTD_ROM
29+
#define MAP_NAME "rom"
30+
#else
31+
#define MAP_NAME "ram"
32+
#endif
33+
34+
static struct map_info uclinux_ram_map = {
35+
.name = MAP_NAME,
36+
.size = 0,
37+
};
38+
39+
static unsigned long physaddr = -1;
40+
module_param(physaddr, ulong, S_IRUGO);
41+
42+
static struct mtd_info *uclinux_ram_mtdinfo;
43+
44+
/****************************************************************************/
45+
46+
static const struct mtd_partition uclinux_romfs[] = {
47+
{ .name = "ROMfs" }
48+
};
49+
50+
#define NUM_PARTITIONS ARRAY_SIZE(uclinux_romfs)
51+
52+
/****************************************************************************/
53+
54+
static int uclinux_point(struct mtd_info *mtd, loff_t from, size_t len,
55+
size_t *retlen, void **virt, resource_size_t *phys)
56+
{
57+
struct map_info *map = mtd->priv;
58+
*virt = map->virt + from;
59+
if (phys)
60+
*phys = map->phys + from;
61+
*retlen = len;
62+
return(0);
63+
}
64+
65+
/****************************************************************************/
66+
67+
static int __init uclinux_mtd_init(void)
68+
{
69+
struct mtd_info *mtd;
70+
struct map_info *mapp;
71+
72+
mapp = &uclinux_ram_map;
73+
74+
if (physaddr == -1)
75+
mapp->phys = (resource_size_t)__bss_stop;
76+
else
77+
mapp->phys = physaddr;
78+
79+
if (!mapp->size)
80+
mapp->size = PAGE_ALIGN(ntohl(*((unsigned long *)(mapp->phys + 8))));
81+
mapp->bankwidth = 4;
82+
83+
printk("uclinux[mtd]: probe address=0x%x size=0x%x\n",
84+
(int) mapp->phys, (int) mapp->size);
85+
86+
/*
87+
* The filesystem is guaranteed to be in direct mapped memory. It is
88+
* directly following the kernels own bss region. Following the same
89+
* mechanism used by architectures setting up traditional initrds we
90+
* use phys_to_virt to get the virtual address of its start.
91+
*/
92+
mapp->virt = phys_to_virt(mapp->phys);
93+
94+
if (mapp->virt == 0) {
95+
printk("uclinux[mtd]: no virtual mapping?\n");
96+
return(-EIO);
97+
}
98+
99+
simple_map_init(mapp);
100+
101+
mtd = do_map_probe("map_" MAP_NAME, mapp);
102+
if (!mtd) {
103+
printk("uclinux[mtd]: failed to find a mapping?\n");
104+
return(-ENXIO);
105+
}
106+
107+
mtd->owner = THIS_MODULE;
108+
mtd->_point = uclinux_point;
109+
mtd->priv = mapp;
110+
111+
uclinux_ram_mtdinfo = mtd;
112+
mtd_device_register(mtd, uclinux_romfs, NUM_PARTITIONS);
113+
114+
return(0);
115+
}
116+
device_initcall(uclinux_mtd_init);
117+
118+
/****************************************************************************/

drivers/mtd/mtd_virt_concat.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ void mtd_virt_concat_destroy_joins(void)
7575
if (item->concat) {
7676
mtd_device_unregister(mtd);
7777
kfree(mtd->name);
78-
mtd_concat_destroy(mtd);
7978
mtd_virt_concat_put_mtd_devices(item->concat);
79+
mtd_concat_destroy(mtd);
8080
}
8181
}
8282
}
@@ -126,8 +126,8 @@ int mtd_virt_concat_destroy(struct mtd_info *mtd)
126126
if (concat->mtd.name) {
127127
del_mtd_device(&concat->mtd);
128128
kfree(concat->mtd.name);
129-
mtd_concat_destroy(&concat->mtd);
130129
mtd_virt_concat_put_mtd_devices(item->concat);
130+
mtd_concat_destroy(&concat->mtd);
131131
}
132132

133133
for (idx = 0; idx < item->count; idx++)
@@ -321,8 +321,10 @@ int mtd_virt_concat_create_join(void)
321321

322322
if (concat->mtd.name) {
323323
ret = memcmp(concat->mtd.name, name, name_sz);
324-
if (ret == 0)
324+
if (ret == 0) {
325+
kfree(name);
325326
continue;
327+
}
326328
}
327329
mtd = mtd_concat_create(concat->subdev, concat->num_subdev, name);
328330
if (!mtd) {

drivers/mtd/mtdcore.c

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,15 @@ static void mtd_release(struct device *dev)
105105
device_destroy(&mtd_class, index + 1);
106106
}
107107

108+
/*
109+
* No-op device release used in add_mtd_device() error paths.
110+
* Prevents mtd_release() from being called via device_release(),
111+
* which would free the mtd_info that the caller still manages.
112+
*/
113+
static void mtd_dev_release_nop(struct device *dev)
114+
{
115+
}
116+
108117
static void mtd_device_release(struct kref *kref)
109118
{
110119
struct mtd_info *mtd = container_of(kref, struct mtd_info, refcnt);
@@ -799,10 +808,8 @@ int add_mtd_device(struct mtd_info *mtd)
799808
mtd_check_of_node(mtd);
800809
of_node_get(mtd_get_of_node(mtd));
801810
error = device_register(&mtd->dev);
802-
if (error) {
803-
put_device(&mtd->dev);
811+
if (error)
804812
goto fail_added;
805-
}
806813

807814
/* Add the nvmem provider */
808815
error = mtd_nvmem_add(mtd);
@@ -840,8 +847,16 @@ int add_mtd_device(struct mtd_info *mtd)
840847
return 0;
841848

842849
fail_nvmem_add:
843-
device_unregister(&mtd->dev);
850+
device_del(&mtd->dev);
844851
fail_added:
852+
/*
853+
* Clear type and set nop release to prevent mtd_release() ->
854+
* release_mtd_partition() -> free_partition() from freeing mtd.
855+
* The caller handles cleanup on failure.
856+
*/
857+
mtd->dev.type = NULL;
858+
mtd->dev.release = mtd_dev_release_nop;
859+
put_device(&mtd->dev);
845860
of_node_put(mtd_get_of_node(mtd));
846861
fail_devname:
847862
idr_remove(&mtd_idr, i);

drivers/mtd/mtdpart.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ static struct mtd_info *allocate_partition(struct mtd_info *parent,
118118
part->name, parent_size - child->part.offset,
119119
child->part.size);
120120
/* register to preserve ordering */
121+
child->part.offset = 0;
122+
child->part.size = 0;
123+
child->erasesize = parent->erasesize;
121124
goto out_register;
122125
}
123126
}
@@ -264,6 +267,11 @@ int mtd_add_partition(struct mtd_info *parent, const char *name,
264267
if (length <= 0)
265268
return -EINVAL;
266269

270+
if (offset < 0 || offset >= (long long)parent_size)
271+
return -EINVAL;
272+
273+
if ((u64)offset + (u64)length > parent_size)
274+
return -EINVAL;
267275
memset(&part, 0, sizeof(part));
268276
part.name = name;
269277
part.size = length;

drivers/mtd/mtdswap.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ struct mtdswap_dev {
125125

126126
char *page_buf;
127127
char *oob_buf;
128+
struct dentry *debugfs_stats;
128129
};
129130

130131
struct mtdswap_oobdata {
@@ -1262,7 +1263,8 @@ static int mtdswap_add_debugfs(struct mtdswap_dev *d)
12621263
if (IS_ERR_OR_NULL(root))
12631264
return -1;
12641265

1265-
debugfs_create_file("mtdswap_stats", S_IRUSR, root, d, &mtdswap_fops);
1266+
d->debugfs_stats = debugfs_create_file("mtdswap_stats", 0400, root,
1267+
d, &mtdswap_fops);
12661268

12671269
return 0;
12681270
}
@@ -1463,6 +1465,7 @@ static void mtdswap_remove_dev(struct mtd_blktrans_dev *dev)
14631465
{
14641466
struct mtdswap_dev *d = MTDSWAP_MBD_TO_MTDSWAP(dev);
14651467

1468+
debugfs_remove(d->debugfs_stats);
14661469
del_mtd_blktrans_dev(dev);
14671470
mtdswap_cleanup(d);
14681471
kfree(d);

drivers/mtd/nand/ecc-mtk.c

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,8 @@ static int mt7622_ecc_regs[] = {
123123
[ECC_DECIRQ_STA] = 0x144,
124124
};
125125

126-
static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc,
127-
enum mtk_ecc_operation op)
126+
static inline int mtk_ecc_wait_idle(struct mtk_ecc *ecc,
127+
enum mtk_ecc_operation op)
128128
{
129129
struct device *dev = ecc->dev;
130130
u32 val;
@@ -136,6 +136,8 @@ static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc,
136136
if (ret)
137137
dev_warn(dev, "%s NOT idle\n",
138138
op == ECC_ENCODE ? "encoder" : "decoder");
139+
140+
return ret;
139141
}
140142

141143
static irqreturn_t mtk_ecc_irq(int irq, void *id)
@@ -265,6 +267,7 @@ static struct mtk_ecc *mtk_ecc_get(struct device_node *np)
265267
{
266268
struct platform_device *pdev;
267269
struct mtk_ecc *ecc;
270+
int ret;
268271

269272
pdev = of_find_device_by_node(np);
270273
if (!pdev)
@@ -276,7 +279,12 @@ static struct mtk_ecc *mtk_ecc_get(struct device_node *np)
276279
return ERR_PTR(-EPROBE_DEFER);
277280
}
278281

279-
clk_prepare_enable(ecc->clk);
282+
ret = clk_prepare_enable(ecc->clk);
283+
if (ret) {
284+
put_device(&pdev->dev);
285+
return ERR_PTR(ret);
286+
}
287+
280288
mtk_ecc_hw_init(ecc);
281289

282290
return ecc;
@@ -312,7 +320,11 @@ int mtk_ecc_enable(struct mtk_ecc *ecc, struct mtk_ecc_config *config)
312320
return ret;
313321
}
314322

315-
mtk_ecc_wait_idle(ecc, op);
323+
ret = mtk_ecc_wait_idle(ecc, op);
324+
if (ret) {
325+
mutex_unlock(&ecc->lock);
326+
return ret;
327+
}
316328

317329
ret = mtk_ecc_config(ecc, config);
318330
if (ret) {
@@ -412,7 +424,9 @@ int mtk_ecc_encode(struct mtk_ecc *ecc, struct mtk_ecc_config *config,
412424
if (ret)
413425
goto timeout;
414426

415-
mtk_ecc_wait_idle(ecc, ECC_ENCODE);
427+
ret = mtk_ecc_wait_idle(ecc, ECC_ENCODE);
428+
if (ret)
429+
goto timeout;
416430

417431
/* Program ECC bytes to OOB: per sector oob = FDM + ECC + SPARE */
418432
len = (config->strength * ecc->caps->parity_bits + 7) >> 3;

drivers/mtd/nand/onenand/onenand_samsung.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,9 @@ static int s5pc110_dma_poll(dma_addr_t dst, dma_addr_t src, size_t count, int di
554554
} while (!(status & S5PC110_DMA_TRANS_STATUS_TD) &&
555555
time_before(jiffies, timeout));
556556

557+
if (!(status & S5PC110_DMA_TRANS_STATUS_TD))
558+
return -ETIMEDOUT;
559+
557560
writel(S5PC110_DMA_TRANS_CMD_TDC, base + S5PC110_DMA_TRANS_CMD);
558561

559562
return 0;
@@ -608,7 +611,9 @@ static int s5pc110_dma_irq(dma_addr_t dst, dma_addr_t src, size_t count, int dir
608611

609612
writel(S5PC110_DMA_TRANS_CMD_TR, base + S5PC110_DMA_TRANS_CMD);
610613

611-
wait_for_completion_timeout(&onenand->complete, msecs_to_jiffies(20));
614+
if (!wait_for_completion_timeout(&onenand->complete,
615+
msecs_to_jiffies(20)))
616+
return -ETIMEDOUT;
612617

613618
return 0;
614619
}

0 commit comments

Comments
 (0)