kernel: backport fix for recently introduced UBI bug
Import commit "ubi: Fix failure attaching when vid_hdr offset equals to (sub)page size" which did not yet make it to stable upstream Linux trees. Fixes: #12232 Fixes: #12339 Signed-off-by: Daniel Golle <daniel@makrotopia.org>
This commit is contained in:
		@@ -0,0 +1,69 @@
 | 
				
			|||||||
 | 
					From 1e020e1b96afdecd20680b5b5be2a6ffc3d27628 Mon Sep 17 00:00:00 2001
 | 
				
			||||||
 | 
					From: Zhihao Cheng <chengzhihao1@huawei.com>
 | 
				
			||||||
 | 
					Date: Mon, 6 Mar 2023 09:33:08 +0800
 | 
				
			||||||
 | 
					Subject: [PATCH] ubi: Fix failure attaching when vid_hdr offset equals to
 | 
				
			||||||
 | 
					 (sub)page size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Following process will make ubi attaching failed since commit
 | 
				
			||||||
 | 
					1b42b1a36fc946 ("ubi: ensure that VID header offset ... size"):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ID="0xec,0xa1,0x00,0x15" # 128M 128KB 2KB
 | 
				
			||||||
 | 
					modprobe nandsim id_bytes=$ID
 | 
				
			||||||
 | 
					flash_eraseall /dev/mtd0
 | 
				
			||||||
 | 
					modprobe ubi mtd="0,2048"  # set vid_hdr offset as 2048 (one page)
 | 
				
			||||||
 | 
					(dmesg):
 | 
				
			||||||
 | 
					  ubi0 error: ubi_attach_mtd_dev [ubi]: VID header offset 2048 too large.
 | 
				
			||||||
 | 
					  UBI error: cannot attach mtd0
 | 
				
			||||||
 | 
					  UBI error: cannot initialize UBI, error -22
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Rework original solution, the key point is making sure
 | 
				
			||||||
 | 
					'vid_hdr_shift + UBI_VID_HDR_SIZE < ubi->vid_hdr_alsize',
 | 
				
			||||||
 | 
					so we should check vid_hdr_shift rather not vid_hdr_offset.
 | 
				
			||||||
 | 
					Then, ubi still support (sub)page aligined VID header offset.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Fixes: 1b42b1a36fc946 ("ubi: ensure that VID header offset ... size")
 | 
				
			||||||
 | 
					Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
 | 
				
			||||||
 | 
					Tested-by: Nicolas Schichan <nschichan@freebox.fr>
 | 
				
			||||||
 | 
					Tested-by: Miquel Raynal <miquel.raynal@bootlin.com> # v5.10, v4.19
 | 
				
			||||||
 | 
					Signed-off-by: Richard Weinberger <richard@nod.at>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					 drivers/mtd/ubi/build.c | 21 +++++++++++++++------
 | 
				
			||||||
 | 
					 1 file changed, 15 insertions(+), 6 deletions(-)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/mtd/ubi/build.c
 | 
				
			||||||
 | 
					+++ b/drivers/mtd/ubi/build.c
 | 
				
			||||||
 | 
					@@ -665,12 +665,6 @@ static int io_init(struct ubi_device *ub
 | 
				
			||||||
 | 
					 	ubi->ec_hdr_alsize = ALIGN(UBI_EC_HDR_SIZE, ubi->hdrs_min_io_size);
 | 
				
			||||||
 | 
					 	ubi->vid_hdr_alsize = ALIGN(UBI_VID_HDR_SIZE, ubi->hdrs_min_io_size);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	if (ubi->vid_hdr_offset && ((ubi->vid_hdr_offset + UBI_VID_HDR_SIZE) >
 | 
				
			||||||
 | 
					-	    ubi->vid_hdr_alsize)) {
 | 
				
			||||||
 | 
					-		ubi_err(ubi, "VID header offset %d too large.", ubi->vid_hdr_offset);
 | 
				
			||||||
 | 
					-		return -EINVAL;
 | 
				
			||||||
 | 
					-	}
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					 	dbg_gen("min_io_size      %d", ubi->min_io_size);
 | 
				
			||||||
 | 
					 	dbg_gen("max_write_size   %d", ubi->max_write_size);
 | 
				
			||||||
 | 
					 	dbg_gen("hdrs_min_io_size %d", ubi->hdrs_min_io_size);
 | 
				
			||||||
 | 
					@@ -688,6 +682,21 @@ static int io_init(struct ubi_device *ub
 | 
				
			||||||
 | 
					 						ubi->vid_hdr_aloffset;
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	/*
 | 
				
			||||||
 | 
					+	 * Memory allocation for VID header is ubi->vid_hdr_alsize
 | 
				
			||||||
 | 
					+	 * which is described in comments in io.c.
 | 
				
			||||||
 | 
					+	 * Make sure VID header shift + UBI_VID_HDR_SIZE not exceeds
 | 
				
			||||||
 | 
					+	 * ubi->vid_hdr_alsize, so that all vid header operations
 | 
				
			||||||
 | 
					+	 * won't access memory out of bounds.
 | 
				
			||||||
 | 
					+	 */
 | 
				
			||||||
 | 
					+	if ((ubi->vid_hdr_shift + UBI_VID_HDR_SIZE) > ubi->vid_hdr_alsize) {
 | 
				
			||||||
 | 
					+		ubi_err(ubi, "Invalid VID header offset %d, VID header shift(%d)"
 | 
				
			||||||
 | 
					+			" + VID header size(%zu) > VID header aligned size(%d).",
 | 
				
			||||||
 | 
					+			ubi->vid_hdr_offset, ubi->vid_hdr_shift,
 | 
				
			||||||
 | 
					+			UBI_VID_HDR_SIZE, ubi->vid_hdr_alsize);
 | 
				
			||||||
 | 
					+		return -EINVAL;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	/* Similar for the data offset */
 | 
				
			||||||
 | 
					 	ubi->leb_start = ubi->vid_hdr_offset + UBI_VID_HDR_SIZE;
 | 
				
			||||||
 | 
					 	ubi->leb_start = ALIGN(ubi->leb_start, ubi->min_io_size);
 | 
				
			||||||
@@ -0,0 +1,69 @@
 | 
				
			|||||||
 | 
					From 1e020e1b96afdecd20680b5b5be2a6ffc3d27628 Mon Sep 17 00:00:00 2001
 | 
				
			||||||
 | 
					From: Zhihao Cheng <chengzhihao1@huawei.com>
 | 
				
			||||||
 | 
					Date: Mon, 6 Mar 2023 09:33:08 +0800
 | 
				
			||||||
 | 
					Subject: [PATCH] ubi: Fix failure attaching when vid_hdr offset equals to
 | 
				
			||||||
 | 
					 (sub)page size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Following process will make ubi attaching failed since commit
 | 
				
			||||||
 | 
					1b42b1a36fc946 ("ubi: ensure that VID header offset ... size"):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ID="0xec,0xa1,0x00,0x15" # 128M 128KB 2KB
 | 
				
			||||||
 | 
					modprobe nandsim id_bytes=$ID
 | 
				
			||||||
 | 
					flash_eraseall /dev/mtd0
 | 
				
			||||||
 | 
					modprobe ubi mtd="0,2048"  # set vid_hdr offset as 2048 (one page)
 | 
				
			||||||
 | 
					(dmesg):
 | 
				
			||||||
 | 
					  ubi0 error: ubi_attach_mtd_dev [ubi]: VID header offset 2048 too large.
 | 
				
			||||||
 | 
					  UBI error: cannot attach mtd0
 | 
				
			||||||
 | 
					  UBI error: cannot initialize UBI, error -22
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Rework original solution, the key point is making sure
 | 
				
			||||||
 | 
					'vid_hdr_shift + UBI_VID_HDR_SIZE < ubi->vid_hdr_alsize',
 | 
				
			||||||
 | 
					so we should check vid_hdr_shift rather not vid_hdr_offset.
 | 
				
			||||||
 | 
					Then, ubi still support (sub)page aligined VID header offset.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Fixes: 1b42b1a36fc946 ("ubi: ensure that VID header offset ... size")
 | 
				
			||||||
 | 
					Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
 | 
				
			||||||
 | 
					Tested-by: Nicolas Schichan <nschichan@freebox.fr>
 | 
				
			||||||
 | 
					Tested-by: Miquel Raynal <miquel.raynal@bootlin.com> # v5.10, v4.19
 | 
				
			||||||
 | 
					Signed-off-by: Richard Weinberger <richard@nod.at>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					 drivers/mtd/ubi/build.c | 21 +++++++++++++++------
 | 
				
			||||||
 | 
					 1 file changed, 15 insertions(+), 6 deletions(-)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/mtd/ubi/build.c
 | 
				
			||||||
 | 
					+++ b/drivers/mtd/ubi/build.c
 | 
				
			||||||
 | 
					@@ -664,12 +664,6 @@ static int io_init(struct ubi_device *ub
 | 
				
			||||||
 | 
					 	ubi->ec_hdr_alsize = ALIGN(UBI_EC_HDR_SIZE, ubi->hdrs_min_io_size);
 | 
				
			||||||
 | 
					 	ubi->vid_hdr_alsize = ALIGN(UBI_VID_HDR_SIZE, ubi->hdrs_min_io_size);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	if (ubi->vid_hdr_offset && ((ubi->vid_hdr_offset + UBI_VID_HDR_SIZE) >
 | 
				
			||||||
 | 
					-	    ubi->vid_hdr_alsize)) {
 | 
				
			||||||
 | 
					-		ubi_err(ubi, "VID header offset %d too large.", ubi->vid_hdr_offset);
 | 
				
			||||||
 | 
					-		return -EINVAL;
 | 
				
			||||||
 | 
					-	}
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					 	dbg_gen("min_io_size      %d", ubi->min_io_size);
 | 
				
			||||||
 | 
					 	dbg_gen("max_write_size   %d", ubi->max_write_size);
 | 
				
			||||||
 | 
					 	dbg_gen("hdrs_min_io_size %d", ubi->hdrs_min_io_size);
 | 
				
			||||||
 | 
					@@ -687,6 +681,21 @@ static int io_init(struct ubi_device *ub
 | 
				
			||||||
 | 
					 						ubi->vid_hdr_aloffset;
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	/*
 | 
				
			||||||
 | 
					+	 * Memory allocation for VID header is ubi->vid_hdr_alsize
 | 
				
			||||||
 | 
					+	 * which is described in comments in io.c.
 | 
				
			||||||
 | 
					+	 * Make sure VID header shift + UBI_VID_HDR_SIZE not exceeds
 | 
				
			||||||
 | 
					+	 * ubi->vid_hdr_alsize, so that all vid header operations
 | 
				
			||||||
 | 
					+	 * won't access memory out of bounds.
 | 
				
			||||||
 | 
					+	 */
 | 
				
			||||||
 | 
					+	if ((ubi->vid_hdr_shift + UBI_VID_HDR_SIZE) > ubi->vid_hdr_alsize) {
 | 
				
			||||||
 | 
					+		ubi_err(ubi, "Invalid VID header offset %d, VID header shift(%d)"
 | 
				
			||||||
 | 
					+			" + VID header size(%zu) > VID header aligned size(%d).",
 | 
				
			||||||
 | 
					+			ubi->vid_hdr_offset, ubi->vid_hdr_shift,
 | 
				
			||||||
 | 
					+			UBI_VID_HDR_SIZE, ubi->vid_hdr_alsize);
 | 
				
			||||||
 | 
					+		return -EINVAL;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	/* Similar for the data offset */
 | 
				
			||||||
 | 
					 	ubi->leb_start = ubi->vid_hdr_offset + UBI_VID_HDR_SIZE;
 | 
				
			||||||
 | 
					 	ubi->leb_start = ALIGN(ubi->leb_start, ubi->min_io_size);
 | 
				
			||||||
@@ -8,7 +8,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
--- a/drivers/mtd/ubi/build.c
 | 
					--- a/drivers/mtd/ubi/build.c
 | 
				
			||||||
+++ b/drivers/mtd/ubi/build.c
 | 
					+++ b/drivers/mtd/ubi/build.c
 | 
				
			||||||
@@ -1192,6 +1192,73 @@ static struct mtd_info * __init open_mtd
 | 
					@@ -1201,6 +1201,73 @@ static struct mtd_info * __init open_mtd
 | 
				
			||||||
 	return mtd;
 | 
					 	return mtd;
 | 
				
			||||||
 }
 | 
					 }
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
@@ -82,7 +82,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
 | 
				
			|||||||
 static int __init ubi_init(void)
 | 
					 static int __init ubi_init(void)
 | 
				
			||||||
 {
 | 
					 {
 | 
				
			||||||
 	int err, i, k;
 | 
					 	int err, i, k;
 | 
				
			||||||
@@ -1275,6 +1342,12 @@ static int __init ubi_init(void)
 | 
					@@ -1284,6 +1351,12 @@ static int __init ubi_init(void)
 | 
				
			||||||
 		}
 | 
					 		}
 | 
				
			||||||
 	}
 | 
					 	}
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
--- a/drivers/mtd/ubi/build.c
 | 
					--- a/drivers/mtd/ubi/build.c
 | 
				
			||||||
+++ b/drivers/mtd/ubi/build.c
 | 
					+++ b/drivers/mtd/ubi/build.c
 | 
				
			||||||
@@ -1191,6 +1191,73 @@ static struct mtd_info * __init open_mtd
 | 
					@@ -1200,6 +1200,73 @@ static struct mtd_info * __init open_mtd
 | 
				
			||||||
 	return mtd;
 | 
					 	return mtd;
 | 
				
			||||||
 }
 | 
					 }
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
@@ -82,7 +82,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
 | 
				
			|||||||
 static int __init ubi_init(void)
 | 
					 static int __init ubi_init(void)
 | 
				
			||||||
 {
 | 
					 {
 | 
				
			||||||
 	int err, i, k;
 | 
					 	int err, i, k;
 | 
				
			||||||
@@ -1274,6 +1341,12 @@ static int __init ubi_init(void)
 | 
					@@ -1283,6 +1350,12 @@ static int __init ubi_init(void)
 | 
				
			||||||
 		}
 | 
					 		}
 | 
				
			||||||
 	}
 | 
					 	}
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user