public inbox for linux-mtd@lists.infradead.org
 help / color / mirror / Atom feed
* [PATCH v2] ubi: gluebi: Fix NULL pointer dereference caused by ftl notifier
@ 2023-10-18 12:16 ZhaoLong Wang
  2023-10-19  1:57 ` Zhihao Cheng
  2023-10-19 20:27 ` Richard Weinberger
  0 siblings, 2 replies; 39+ messages in thread
From: ZhaoLong Wang @ 2023-10-18 12:16 UTC (permalink / raw)
  To: richard, miquel.raynal, vigneshr, dpervushin, Artem.Bityutskiy
  Cc: linux-mtd, linux-kernel, chengzhihao1, wangzhaolong1, yi.zhang,
	yangerkun

If both flt.ko and gluebi.ko are loaded, the notiier of ftl
triggers NULL pointer dereference when trying to access
‘gluebi->desc’ in gluebi_read().

ubi_gluebi_init
  ubi_register_volume_notifier
    ubi_enumerate_volumes
      ubi_notify_all
        gluebi_notify    nb->notifier_call()
          gluebi_create
            mtd_device_register
              mtd_device_parse_register
                add_mtd_device
                  blktrans_notify_add   not->add()
                    ftl_add_mtd         tr->add_mtd()
                      scan_header
                        mtd_read
                          mtd_read
                            mtd_read_oob
                              gluebi_read   mtd->read()
                                gluebi->desc - NULL

Detailed reproduction information available at the link[1],

In the normal case, obtain gluebi->desc in the gluebi_get_device(),
and accesses gluebi->desc in the gluebi_read(). However,
gluebi_get_device() is not executed in advance in the
ftl_add_mtd() process, which leads to NULL pointer dereference.

The value of gluebi->desc may also be a negative error code, which
triggers the page fault error.

This patch has the following modifications:

1. Do not assign gluebi->desc to the error code. Use the NULL instead.

2. Always check the validity of gluebi->desc in gluebi_read() If the
   gluebi->desc is NULL, try to get MTD device.

Such a modification currently works because the mutex "mtd_table_mutex"
is held on all necessary paths, including the ftl_add_mtd() call path,
open and close paths. Therefore, many race condition can be avoided.

Fixes: 2ba3d76a1e29 ("UBI: make gluebi a separate module")
Link: https://bugzilla.kernel.org/show_bug.cgi?id=217992 [1]
Signed-off-by: ZhaoLong Wang <wangzhaolong1@huawei.com>
---
 drivers/mtd/ubi/gluebi.c | 37 +++++++++++++++++++++++++++++++------
 1 file changed, 31 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/ubi/gluebi.c b/drivers/mtd/ubi/gluebi.c
index 1b980d15d9fb..0ca7f104adbf 100644
--- a/drivers/mtd/ubi/gluebi.c
+++ b/drivers/mtd/ubi/gluebi.c
@@ -85,6 +85,7 @@ static int gluebi_get_device(struct mtd_info *mtd)
 {
 	struct gluebi_device *gluebi;
 	int ubi_mode = UBI_READONLY;
+	struct ubi_volume_desc *vdesc;
 
 	if (mtd->flags & MTD_WRITEABLE)
 		ubi_mode = UBI_READWRITE;
@@ -109,12 +110,14 @@ static int gluebi_get_device(struct mtd_info *mtd)
 	 * This is the first reference to this UBI volume via the MTD device
 	 * interface. Open the corresponding volume in read-write mode.
 	 */
-	gluebi->desc = ubi_open_volume(gluebi->ubi_num, gluebi->vol_id,
+	vdesc = ubi_open_volume(gluebi->ubi_num, gluebi->vol_id,
 				       ubi_mode);
-	if (IS_ERR(gluebi->desc)) {
+	if (IS_ERR(vdesc)) {
+		gluebi->desc = NULL;
 		mutex_unlock(&devices_mutex);
-		return PTR_ERR(gluebi->desc);
+		return PTR_ERR(vdesc);
 	}
+	gluebi->desc = vdesc;
 	gluebi->refcnt += 1;
 	mutex_unlock(&devices_mutex);
 	return 0;
@@ -134,8 +137,10 @@ static void gluebi_put_device(struct mtd_info *mtd)
 	gluebi = container_of(mtd, struct gluebi_device, mtd);
 	mutex_lock(&devices_mutex);
 	gluebi->refcnt -= 1;
-	if (gluebi->refcnt == 0)
+	if (gluebi->refcnt == 0) {
 		ubi_close_volume(gluebi->desc);
+		gluebi->desc = NULL;
+	}
 	mutex_unlock(&devices_mutex);
 }
 
@@ -154,9 +159,26 @@ static int gluebi_read(struct mtd_info *mtd, loff_t from, size_t len,
 		       size_t *retlen, unsigned char *buf)
 {
 	int err = 0, lnum, offs, bytes_left;
-	struct gluebi_device *gluebi;
+	struct gluebi_device *gluebi = container_of(mtd, struct gluebi_device,
+						    mtd);
+	int no_desc = gluebi->desc == NULL ? 1 : 0;
+
+	/**
+	 * In normal case, the UBI volume desc has been initialized by
+	 * ->_get_device(). However, in the ftl notifier process, the
+	 * ->_get_device() is not executed in advance and the MTD device
+	 * is directly scanned which cause NULL pointer dereference.
+	 * Therefore, try to get the MTD device here.
+	 */
+	if (unlikely(no_desc)) {
+		err = __get_mtd_device(mtd);
+		if (err) {
+			err_msg("cannot get MTD device %d, UBI device %d, volume %d, error %d",
+				mtd->index, gluebi->ubi_num, gluebi->vol_id, err);
+			return err;
+		}
+	}
 
-	gluebi = container_of(mtd, struct gluebi_device, mtd);
 	lnum = div_u64_rem(from, mtd->erasesize, &offs);
 	bytes_left = len;
 	while (bytes_left) {
@@ -176,6 +198,9 @@ static int gluebi_read(struct mtd_info *mtd, loff_t from, size_t len,
 	}
 
 	*retlen = len - bytes_left;
+
+	if (unlikely(no_desc))
+		__put_mtd_device(mtd);
 	return err;
 }
 
-- 
2.31.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply related	[flat|nested] 39+ messages in thread
[parent not found: <CFAC276E-E652-40CD-B3D8-563B95E679A8@mac.com>]

end of thread, other threads:[~2024-06-24 19:00 UTC | newest]

Thread overview: 39+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-10-18 12:16 [PATCH v2] ubi: gluebi: Fix NULL pointer dereference caused by ftl notifier ZhaoLong Wang
2023-10-19  1:57 ` Zhihao Cheng
2023-10-19 20:27 ` Richard Weinberger
2023-10-20  2:27   ` Zhihao Cheng
2023-10-21 16:09     ` Richard Weinberger
2023-10-23  6:41       ` ZhaoLong Wang
2023-10-23  6:46         ` Richard Weinberger
2023-10-23  7:12           ` ZhaoLong Wang
2023-10-23  7:16             ` Richard Weinberger
2023-10-23  7:09       ` Zhihao Cheng
2023-10-23  7:15         ` Richard Weinberger
2023-10-23  7:36           ` Zhihao Cheng
     [not found] <CFAC276E-E652-40CD-B3D8-563B95E679A8@mac.com>
2024-06-17 14:31 ` Richard Weinberger
2024-06-17 15:42 ` Richard Weinberger
     [not found]   ` <14779870-BA54-4ABF-8ABF-FF1D23D172A7@mac.com>
2024-06-17 16:00     ` Richard Weinberger
2024-06-17 16:05       ` Gagan Sidhu
2024-06-17 16:52         ` Richard Weinberger
     [not found]           ` <E3E2C13C-1E52-46F2-BE2D-D2592C3369DB@mac.com>
2024-06-17 17:33             ` Gagan Sidhu
2024-06-17 17:48               ` Gagan Sidhu
2024-06-17 18:09                 ` Richard Weinberger
2024-06-17 18:18                   ` Gagan Sidhu
2024-06-17 18:32                     ` Richard Weinberger
2024-06-17 18:46                       ` Gagan Sidhu
2024-06-17 18:52                         ` Richard Weinberger
2024-06-17 20:29                           ` Daniel Golle
2024-06-17 21:22                             ` Gagan Sidhu
2024-06-17 22:13                               ` Gagan Sidhu
2024-06-18  4:03                                 ` Zhihao Cheng
2024-06-20 22:06                                   ` Gagan Sidhu
2024-06-21  1:59                                     ` Zhihao Cheng
2024-06-21  2:09                                       ` Gagan Sidhu
2024-06-21  3:03                                         ` Zhihao Cheng
2024-06-21  4:27                                           ` Gagan Sidhu
2024-06-21  4:55                                             ` Zhihao Cheng
2024-06-21 11:36                                               ` Gagan Sidhu
2024-06-22  2:37                                                 ` Zhihao Cheng
2024-06-22  2:43                                                   ` Gagan Sidhu
2024-06-22 21:07                                                     ` Daniel Golle
2024-06-24 19:00                                                       ` Gagan Sidhu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox