Re: [PATCH v2] ubi: gluebi: Fix NULL pointer dereference caused by ftl notifier

From: Zhihao Cheng
Date: Thu Oct 19 2023 - 22:28:45 EST


在 2023/10/20 4:27, Richard Weinberger 写道:
----- Ursprüngliche Mail -----
Von: "ZhaoLong Wang" <wangzhaolong1@xxxxxxxxxx>
An: "richard" <richard@xxxxxx>, "Miquel Raynal" <miquel.raynal@xxxxxxxxxxx>, "Vignesh Raghavendra" <vigneshr@xxxxxx>,
dpervushin@xxxxxxxxxxxxxxxxx, "Artem Bityutskiy" <Artem.Bityutskiy@xxxxxxxxx>
CC: "linux-mtd" <linux-mtd@xxxxxxxxxxxxxxxxxxx>, "linux-kernel" <linux-kernel@xxxxxxxxxxxxxxx>, "chengzhihao1"
<chengzhihao1@xxxxxxxxxx>, "ZhaoLong Wang" <wangzhaolong1@xxxxxxxxxx>, "yi zhang" <yi.zhang@xxxxxxxxxx>, "yangerkun"
<yangerkun@xxxxxxxxxx>
Gesendet: Mittwoch, 18. Oktober 2023 14:16:18
Betreff: [PATCH v2] ubi: gluebi: Fix NULL pointer dereference caused by ftl notifier

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.

I see the problem, but I'm not really satisfied by the solution.
Adding this hack to gluebi_read() is not nice at all.

Yes, it's jsut a workaround. At the begining, I prefer that increasing volume refcnt (by ubi_open_volume) in gluebi_create and releasing volume refcnt in gluebi_remove. It looks more reasonable that holding a refcnt of UBI volume when gluebi is alive. After looking through the code, the creation/destroying of gluebi is triggered by volume actions(UBI_VOLUME_ADDED/UBI_VOLUME_REMOVED), which means that:
1. gluebi_remove is depended on UBI_VOLUME_REMOVED(triggered by ubi_remove_volume)
2. ubi_remove_volume won't be executed until the refcnt of volume becomes 0(released by gluebi_remove)

If we add new ioctls to control creation/destroying of gluebi, then gluebi mtd won't be automatically created when UBI volume is added. I'm not certain whether this change will effect existing startup process that depends on gluebi.


Is there a strong reason why have to defer ubi_open_volume() to
gluebi_get_device()?

Miquel, what do you think?

Thanks,
//richard

.