]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 29 Nov 2018 08:13:20 +0000 (09:13 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 29 Nov 2018 08:13:20 +0000 (09:13 +0100)
added patches:
mtd-rawnand-atmel-fix-of-child-node-lookup.patch
ubi-fastmap-check-each-mapping-only-once.patch

queue-4.14/mtd-rawnand-atmel-fix-of-child-node-lookup.patch [new file with mode: 0644]
queue-4.14/series
queue-4.14/ubi-fastmap-check-each-mapping-only-once.patch [new file with mode: 0644]

diff --git a/queue-4.14/mtd-rawnand-atmel-fix-of-child-node-lookup.patch b/queue-4.14/mtd-rawnand-atmel-fix-of-child-node-lookup.patch
new file mode 100644 (file)
index 0000000..fdc8073
--- /dev/null
@@ -0,0 +1,67 @@
+From 5d1e9c2212ea6b4dd735e4fc3dd6279a365d5d10 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Mon, 27 Aug 2018 10:21:49 +0200
+Subject: mtd: rawnand: atmel: fix OF child-node lookup
+
+From: Johan Hovold <johan@kernel.org>
+
+commit 5d1e9c2212ea6b4dd735e4fc3dd6279a365d5d10 upstream.
+
+Use the new of_get_compatible_child() helper to lookup the nfc child
+node instead of using of_find_compatible_node(), which searches the
+entire tree from a given start node and thus can return an unrelated
+(i.e. non-child) node.
+
+This also addresses a potential use-after-free (e.g. after probe
+deferral) as the tree-wide helper drops a reference to its first
+argument (i.e. the node of the device being probed).
+
+While at it, also fix a related nfc-node reference leak.
+
+Fixes: f88fc122cc34 ("mtd: nand: Cleanup/rework the atmel_nand driver")
+Cc: stable <stable@vger.kernel.org>     # 4.11
+Cc: Nicolas Ferre <nicolas.ferre@microchip.com>
+Cc: Josh Wu <rainyfeeling@outlook.com>
+Cc: Boris Brezillon <boris.brezillon@bootlin.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/mtd/nand/atmel/nand-controller.c |   11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+--- a/drivers/mtd/nand/atmel/nand-controller.c
++++ b/drivers/mtd/nand/atmel/nand-controller.c
+@@ -2077,8 +2077,7 @@ atmel_hsmc_nand_controller_legacy_init(s
+       int ret;
+       nand_np = dev->of_node;
+-      nfc_np = of_find_compatible_node(dev->of_node, NULL,
+-                                       "atmel,sama5d3-nfc");
++      nfc_np = of_get_compatible_child(dev->of_node, "atmel,sama5d3-nfc");
+       if (!nfc_np) {
+               dev_err(dev, "Could not find device node for sama5d3-nfc\n");
+               return -ENODEV;
+@@ -2492,15 +2491,19 @@ static int atmel_nand_controller_probe(s
+       }
+       if (caps->legacy_of_bindings) {
++              struct device_node *nfc_node;
+               u32 ale_offs = 21;
+               /*
+                * If we are parsing legacy DT props and the DT contains a
+                * valid NFC node, forward the request to the sama5 logic.
+                */
+-              if (of_find_compatible_node(pdev->dev.of_node, NULL,
+-                                          "atmel,sama5d3-nfc"))
++              nfc_node = of_get_compatible_child(pdev->dev.of_node,
++                                                 "atmel,sama5d3-nfc");
++              if (nfc_node) {
+                       caps = &atmel_sama5_nand_caps;
++                      of_node_put(nfc_node);
++              }
+               /*
+                * Even if the compatible says we are dealing with an
index a6bcd28455c1a66c754f6727e09b2bd9a6ca22ee..f6408ec4fd891eea8f257dcf24ba66d5032b849d 100644 (file)
@@ -72,3 +72,5 @@ power-supply-twl4030-charger-fix-of-sibling-node-loo.patch
 arm64-remove-no-op-p-linker-flag.patch
 xhci-allow-more-than-32-quirks.patch
 xhci-add-quirk-to-workaround-the-errata-seen-on-cavium-thunder-x2-soc.patch
+mtd-rawnand-atmel-fix-of-child-node-lookup.patch
+ubi-fastmap-check-each-mapping-only-once.patch
diff --git a/queue-4.14/ubi-fastmap-check-each-mapping-only-once.patch b/queue-4.14/ubi-fastmap-check-each-mapping-only-once.patch
new file mode 100644 (file)
index 0000000..3cad2f2
--- /dev/null
@@ -0,0 +1,177 @@
+From 34653fd8c46e771585fce5975e4243f8fd401914 Mon Sep 17 00:00:00 2001
+From: Richard Weinberger <richard@nod.at>
+Date: Mon, 28 May 2018 22:04:33 +0200
+Subject: ubi: fastmap: Check each mapping only once
+
+From: Richard Weinberger <richard@nod.at>
+
+commit 34653fd8c46e771585fce5975e4243f8fd401914 upstream.
+
+Maintain a bitmap to keep track of which LEB->PEB mapping
+was checked already.
+That way we have to read back VID headers only once.
+
+Fixes: a23cf10d9abb ("ubi: fastmap: Correctly handle interrupted erasures in EBA")
+Signed-off-by: Richard Weinberger <richard@nod.at>
+Signed-off-by: Martin Kepplinger <martin.kepplinger@ginzinger.com>
+
+---
+ drivers/mtd/ubi/build.c   |    1 +
+ drivers/mtd/ubi/eba.c     |    4 ++++
+ drivers/mtd/ubi/fastmap.c |   20 ++++++++++++++++++++
+ drivers/mtd/ubi/ubi.h     |   11 +++++++++++
+ drivers/mtd/ubi/vmt.c     |    1 +
+ drivers/mtd/ubi/vtbl.c    |   16 +++++++++++++++-
+ 6 files changed, 52 insertions(+), 1 deletion(-)
+
+--- a/drivers/mtd/ubi/build.c
++++ b/drivers/mtd/ubi/build.c
+@@ -526,6 +526,7 @@ void ubi_free_internal_volumes(struct ub
+       for (i = ubi->vtbl_slots;
+            i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) {
+               ubi_eba_replace_table(ubi->volumes[i], NULL);
++              ubi_fastmap_destroy_checkmap(ubi->volumes[i]);
+               kfree(ubi->volumes[i]);
+       }
+ }
+--- a/drivers/mtd/ubi/eba.c
++++ b/drivers/mtd/ubi/eba.c
+@@ -517,6 +517,9 @@ static int check_mapping(struct ubi_devi
+       if (!ubi->fast_attach)
+               return 0;
++      if (!vol->checkmap || test_bit(lnum, vol->checkmap))
++              return 0;
++
+       vidb = ubi_alloc_vid_buf(ubi, GFP_NOFS);
+       if (!vidb)
+               return -ENOMEM;
+@@ -551,6 +554,7 @@ static int check_mapping(struct ubi_devi
+               goto out_free;
+       }
++      set_bit(lnum, vol->checkmap);
+       err = 0;
+ out_free:
+--- a/drivers/mtd/ubi/fastmap.c
++++ b/drivers/mtd/ubi/fastmap.c
+@@ -1101,6 +1101,26 @@ free_fm_sb:
+       goto out;
+ }
++int ubi_fastmap_init_checkmap(struct ubi_volume *vol, int leb_count)
++{
++      struct ubi_device *ubi = vol->ubi;
++
++      if (!ubi->fast_attach)
++              return 0;
++
++      vol->checkmap = kcalloc(BITS_TO_LONGS(leb_count), sizeof(unsigned long),
++                              GFP_KERNEL);
++      if (!vol->checkmap)
++              return -ENOMEM;
++
++      return 0;
++}
++
++void ubi_fastmap_destroy_checkmap(struct ubi_volume *vol)
++{
++      kfree(vol->checkmap);
++}
++
+ /**
+  * ubi_write_fastmap - writes a fastmap.
+  * @ubi: UBI device object
+--- a/drivers/mtd/ubi/ubi.h
++++ b/drivers/mtd/ubi/ubi.h
+@@ -334,6 +334,9 @@ struct ubi_eba_leb_desc {
+  * @changing_leb: %1 if the atomic LEB change ioctl command is in progress
+  * @direct_writes: %1 if direct writes are enabled for this volume
+  *
++ * @checkmap: bitmap to remember which PEB->LEB mappings got checked,
++ *            protected by UBI LEB lock tree.
++ *
+  * The @corrupted field indicates that the volume's contents is corrupted.
+  * Since UBI protects only static volumes, this field is not relevant to
+  * dynamic volumes - it is user's responsibility to assure their data
+@@ -377,6 +380,10 @@ struct ubi_volume {
+       unsigned int updating:1;
+       unsigned int changing_leb:1;
+       unsigned int direct_writes:1;
++
++#ifdef CONFIG_MTD_UBI_FASTMAP
++      unsigned long *checkmap;
++#endif
+ };
+ /**
+@@ -965,8 +972,12 @@ size_t ubi_calc_fm_size(struct ubi_devic
+ int ubi_update_fastmap(struct ubi_device *ubi);
+ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai,
+                    struct ubi_attach_info *scan_ai);
++int ubi_fastmap_init_checkmap(struct ubi_volume *vol, int leb_count);
++void ubi_fastmap_destroy_checkmap(struct ubi_volume *vol);
+ #else
+ static inline int ubi_update_fastmap(struct ubi_device *ubi) { return 0; }
++int static inline ubi_fastmap_init_checkmap(struct ubi_volume *vol, int leb_count) { return 0; }
++static inline void ubi_fastmap_destroy_checkmap(struct ubi_volume *vol) {}
+ #endif
+ /* block.c */
+--- a/drivers/mtd/ubi/vmt.c
++++ b/drivers/mtd/ubi/vmt.c
+@@ -139,6 +139,7 @@ static void vol_release(struct device *d
+       struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev);
+       ubi_eba_replace_table(vol, NULL);
++      ubi_fastmap_destroy_checkmap(vol);
+       kfree(vol);
+ }
+--- a/drivers/mtd/ubi/vtbl.c
++++ b/drivers/mtd/ubi/vtbl.c
+@@ -534,7 +534,7 @@ static int init_volumes(struct ubi_devic
+                       const struct ubi_attach_info *ai,
+                       const struct ubi_vtbl_record *vtbl)
+ {
+-      int i, reserved_pebs = 0;
++      int i, err, reserved_pebs = 0;
+       struct ubi_ainf_volume *av;
+       struct ubi_volume *vol;
+@@ -620,6 +620,16 @@ static int init_volumes(struct ubi_devic
+                       (long long)(vol->used_ebs - 1) * vol->usable_leb_size;
+               vol->used_bytes += av->last_data_size;
+               vol->last_eb_bytes = av->last_data_size;
++
++              /*
++               * We use ubi->peb_count and not vol->reserved_pebs because
++               * we want to keep the code simple. Otherwise we'd have to
++               * resize/check the bitmap upon volume resize too.
++               * Allocating a few bytes more does not hurt.
++               */
++              err = ubi_fastmap_init_checkmap(vol, ubi->peb_count);
++              if (err)
++                      return err;
+       }
+       /* And add the layout volume */
+@@ -645,6 +655,9 @@ static int init_volumes(struct ubi_devic
+       reserved_pebs += vol->reserved_pebs;
+       ubi->vol_count += 1;
+       vol->ubi = ubi;
++      err = ubi_fastmap_init_checkmap(vol, UBI_LAYOUT_VOLUME_EBS);
++      if (err)
++              return err;
+       if (reserved_pebs > ubi->avail_pebs) {
+               ubi_err(ubi, "not enough PEBs, required %d, available %d",
+@@ -849,6 +862,7 @@ int ubi_read_volume_table(struct ubi_dev
+ out_free:
+       vfree(ubi->vtbl);
+       for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) {
++              ubi_fastmap_destroy_checkmap(ubi->volumes[i]);
+               kfree(ubi->volumes[i]);
+               ubi->volumes[i] = NULL;
+       }