Commit 844c6fdc authored by Zhihao Cheng's avatar Zhihao Cheng Committed by Richard Weinberger
Browse files

ubi: Revert "ubi: wl: Close down wear-leveling before nand is suspended"

Commit 5580cdae ("ubi: wl: Close down wear-leveling before nand is
suspended") added a reboot notification in UBI layer to shutdown the
wear-leveling subsystem, which imported an UAF problem[1]. Besides that,
the method also brings other potential UAF problems, for example:
       reboot             kworker
 ubi_wl_reboot_notifier
  ubi_wl_close
   ubi_fastmap_close
    kfree(ubi->fm)
                     update_fastmap_work_fn
		      ubi_update_fastmap
		       old_fm = ubi->fm
		       if (old_fm && old_fm->e[i]) // UAF!

Actually, the problem fixed by commit 5580cdae ("ubi: wl: Close down
wear-leveling before nand is suspended") has been solved by commit
8cba3234 ("mtd: rawnand: protect access to rawnand devices while in
suspend"), which was discussed in [2]. So we can revert the commit
5580cdae ("ubi: wl: Close down wear-leveling before nand is
suspended") directly.

[1] https://lore.kernel.org/linux-mtd/20241208175211.9406-2-dennis.lamerice@gmail.com/
[2] https://lore.kernel.org/all/9bf76f5d-12a4-46ff-90d4-4a7f0f47c381@axis.com/



Fixes: 5580cdae ("ubi: wl: Close down wear-leveling before nand is suspended")
Reported-by: default avatarDennis Lam <dennis.lamerice@gmail.com>
Closes: https://lore.kernel.org/linux-mtd/20241208175211.9406-2-dennis.lamerice@gmail.com/


Signed-off-by: default avatarZhihao Cheng <chengzhihao1@huawei.com>
Acked-by: default avatarMårten Lindahl <marten.lindahl@axis.com>
Signed-off-by: default avatarRichard Weinberger <richard@nod.at>
parent 404de7ab
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -549,7 +549,6 @@ struct ubi_debug_info {
 * @peb_buf: a buffer of PEB size used for different purposes
 * @buf_mutex: protects @peb_buf
 * @ckvol_mutex: serializes static volume checking when opening
 * @wl_reboot_notifier: close all wear-leveling work before reboot
 *
 * @dbg: debugging information for this UBI device
 */
@@ -652,7 +651,6 @@ struct ubi_device {
	void *peb_buf;
	struct mutex buf_mutex;
	struct mutex ckvol_mutex;
	struct notifier_block wl_reboot_notifier;

	struct ubi_debug_info dbg;
};
+0 −21
Original line number Diff line number Diff line
@@ -89,7 +89,6 @@
#include <linux/crc32.h>
#include <linux/freezer.h>
#include <linux/kthread.h>
#include <linux/reboot.h>
#include "ubi.h"
#include "wl.h"

@@ -128,8 +127,6 @@ static int self_check_in_wl_tree(const struct ubi_device *ubi,
				 struct ubi_wl_entry *e, struct rb_root *root);
static int self_check_in_pq(const struct ubi_device *ubi,
			    struct ubi_wl_entry *e);
static int ubi_wl_reboot_notifier(struct notifier_block *n,
				  unsigned long state, void *cmd);

/**
 * wl_tree_add - add a wear-leveling entry to a WL RB-tree.
@@ -1953,13 +1950,6 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
	if (!ubi->ro_mode && !ubi->fm_disabled)
		ubi_ensure_anchor_pebs(ubi);
#endif

	if (!ubi->wl_reboot_notifier.notifier_call) {
		ubi->wl_reboot_notifier.notifier_call = ubi_wl_reboot_notifier;
		ubi->wl_reboot_notifier.priority = 1; /* Higher than MTD */
		register_reboot_notifier(&ubi->wl_reboot_notifier);
	}

	return 0;

out_free:
@@ -2005,17 +1995,6 @@ void ubi_wl_close(struct ubi_device *ubi)
	kfree(ubi->lookuptbl);
}

static int ubi_wl_reboot_notifier(struct notifier_block *n,
				  unsigned long state, void *cmd)
{
	struct ubi_device *ubi;

	ubi = container_of(n, struct ubi_device, wl_reboot_notifier);
	ubi_wl_close(ubi);

	return NOTIFY_DONE;
}

/**
 * self_check_ec - make sure that the erase counter of a PEB is correct.
 * @ubi: UBI device description object