ubiblock: null pointer dereference using scatterlist in work_queue

Stephan Wurm stephan.wurm at a-eberle.de
Mon Jul 17 07:55:58 PDT 2023


Am 23-07-17 01:03 schrieb Richard Weinberger:
> Stephan,
>
> ----- Ursprüngliche Mail -----
> > Von: "Stephan Wurm" <stephan.wurm at a-eberle.de>
> >> So reading from ubiblock works as long you don't access it via dm-verity?
> >> How about other stacked devices such as dmcrypt?
> >
> > We did not check other stacked devices, but we'll give this a try.
>
> Please apply this patch too:
>
> diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c
> index 75eaecc8639f0..795e2d0f61086 100644
> --- a/drivers/mtd/ubi/block.c
> +++ b/drivers/mtd/ubi/block.c
> @@ -304,7 +304,7 @@ static void ubiblock_do_work(struct work_struct *work)
>          * the number of sg entries is limited to UBI_MAX_SG_COUNT
>          * and ubi_read_sg() will check that limit.
>          */
> -       blk_rq_map_sg(req->q, req, pdu->usgl.sg);
> +       ubi_assert(blk_rq_map_sg(req->q, req, pdu->usgl.sg) > 0);
>
>         ret = ubiblock_read(pdu);
>
>
> I fear the assert will fail. But let's see. :-D
> At least it would explain the NULL deref.

I have now applied the following patch, including yours and additional debug
output around the scatterlist:

diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c
index 75eaecc8639f..fea959a4b0ef 100644
--- a/drivers/mtd/ubi/block.c
+++ b/drivers/mtd/ubi/block.c
@@ -96,6 +96,16 @@ static DEFINE_IDR(ubiblock_minor_idr);
 static DEFINE_MUTEX(devices_mutex);
 static int ubiblock_major;

+static void ubiblock_print_scatterlist(struct ubiblock_pdu *pdu)
+{
+	int ret = sg_nents(&pdu->usgl.sg[0]);
+	for (int i = 0; i < ret; i++) {
+		struct scatterlist *sg = &pdu->usgl.sg[i];
+		pr_warn("sgl[%08d] => %px: page_link=%lu, offset=%d, length=%d",
+			i, sg_virt(sg), sg->page_link, sg->offset, sg->length);
+	}
+}
+
 static int __init ubiblock_set_param(const char *val,
 				     const struct kernel_param *kp)
 {
@@ -304,7 +314,9 @@ static void ubiblock_do_work(struct work_struct *work)
 	 * the number of sg entries is limited to UBI_MAX_SG_COUNT
 	 * and ubi_read_sg() will check that limit.
 	 */
-	blk_rq_map_sg(req->q, req, pdu->usgl.sg);
+	ubi_assert(blk_rq_map_sg(req->q, req, pdu->usgl.sg) > 0);
+
+	ubiblock_print_scatterlist(pdu);

 	ret = ubiblock_read(pdu);

diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index 4e1d80746b04..361e4ce44172 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -748,10 +748,15 @@ int ubi_eba_read_leb_sg(struct ubi_device *ubi, struct ubi_volume *vol,
 			struct ubi_sgl *sgl, int lnum, int offset, int len,
 			int check)
 {
+	static int count[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
 	int to_read;
 	int ret;
 	struct scatterlist *sg;

+	count[vol->vol_id]++;
+
+	pr_warn("%dnth call of ubi_ea_read_leb_sg", count[vol->vol_id]);
+
 	for (;;) {
 		ubi_assert(sgl->list_pos < UBI_MAX_SG_COUNT);
 		sg = &sgl->sg[sgl->list_pos];

As you can see in following log excerpt, we are able to pass the new assert:

[   49.830833] sgl[00000000] => c30e9000: page_link=4018515232, offset=0, length=4096
[   49.835267] sgl[00000001] => c834f000: page_link=4019190242, offset=0, length=4096
[   49.843009] 46nth call of ubi_ea_read_leb_sg
[   49.862017] sgl[00000000] => c5948000: page_link=4018845954, offset=0, length=4096
[   49.866388] 47nth call of ubi_ea_read_leb_sg
[   49.880518] sgl[00000000] => c5479000: page_link=4018806560, offset=0, length=4096
[   49.884942] sgl[00000001] => c80f6000: page_link=4019171010, offset=0, length=4096
[   49.892720] 48nth call of ubi_ea_read_leb_sg
[   49.913535] sgl[00000000] => c2b1f000: page_link=4018467808, offset=0, length=4096
[   49.917961] sgl[00000001] => c5544000: page_link=4018813056, offset=0, length=4096
[   49.925691] sgl[00000002] => c2bae000: page_link=4018472384, offset=0, length=4096
[   49.933520] sgl[00000003] => c2bad000: page_link=4018472354, offset=0, length=4096
[   49.941239] 49nth call of ubi_ea_read_leb_sg
[   49.955981] sgl[00000000] => c5b77000: page_link=4018863840, offset=0, length=4096
[   49.960476] sgl[00000001] => c834c000: page_link=4019190144, offset=0, length=4096
[   49.968119] sgl[00000002] => c5547000: page_link=4018813152, offset=0, length=4096
[   49.975835] sgl[00000003] => c5bb4000: page_link=4018865792, offset=0, length=4096
[   49.983541] sgl[00000004] => c59e0000: page_link=4018850816, offset=0, length=4096
[   49.991244] sgl[00000005] => c58b8000: page_link=4018841344, offset=0, length=4096
[   49.998942] sgl[00000006] => c818d000: page_link=4019175840, offset=0, length=4096
[   50.006577] sgl[00000007] => c4b3e000: page_link=4018730944, offset=0, length=4096
[   50.014321] sgl[00000008] => c5895000: page_link=4018840224, offset=0, length=4096
[   50.022035] sgl[00000009] => c317b000: page_link=4018519904, offset=0, length=4096
[   50.029735] sgl[00000010] => c52c3000: page_link=4018792544, offset=0, length=4096
[   50.037372] sgl[00000011] => c5822000: page_link=4018836544, offset=0, length=4096
[   50.045105] sgl[00000012] => c557d000: page_link=4018814880, offset=0, length=4096
[   50.052814] sgl[00000013] => c5423000: page_link=4018803808, offset=0, length=4096
[   50.060513] sgl[00000014] => c8289000: page_link=4019183904, offset=0, length=4096
[   50.068221] sgl[00000015] => c8398000: page_link=4019192576, offset=0, length=4096
[   50.075860] sgl[00000016] => c66db000: page_link=4018957152, offset=0, length=4096
[   50.083561] sgl[00000017] => c585b000: page_link=4018838368, offset=0, length=4096
[   50.091263] sgl[00000018] => c801c000: page_link=4019164034, offset=0, length=4096
[   50.098961] 50nth call of ubi_ea_read_leb_sg
[   50.155499] 51nth call of ubi_ea_read_leb_sg
[   50.248918] sgl[00000000] => c59a1000: page_link=4018848800, offset=0, length=4096
[   50.253355] sgl[00000001] => c810c000: page_link=4019171714, offset=0, length=4096
[   50.261120] 52nth call of ubi_ea_read_leb_sg
[   50.277054] sgl[00000000] => c5bb2000: page_link=4018865728, offset=0, length=4096
[   50.281549] sgl[00000001] => c5695000: page_link=4018823840, offset=0, length=4096
[   50.289255] sgl[00000002] => c80db000: page_link=4019170144, offset=0, length=4096
[   50.296894] sgl[00000003] => c50f7000: page_link=4018777824, offset=0, length=4096
[   50.304597] sgl[00000004] => c5c42000: page_link=4018870336, offset=0, length=4096
[   50.312301] sgl[00000005] => c55b8000: page_link=4018816770, offset=0, length=4096
[   50.320108] 53nth call of ubi_ea_read_leb_sg
[   50.333646] sgl[00000000] => c53f2000: page_link=4018802240, offset=0, length=4096
[   50.338065] sgl[00000001] => c5386000: page_link=4018798784, offset=0, length=4096
[   50.345882] sgl[00000002] => c56b0000: page_link=4018824704, offset=0, length=4096
[   50.353646] sgl[00000003] => c6819000: page_link=4018967328, offset=0, length=4096
[   50.361362] sgl[00000004] => c442e000: page_link=4018673088, offset=0, length=4096
[   50.369100] sgl[00000005] => c442c000: page_link=4018673024, offset=0, length=4096
[   50.376736] sgl[00000006] => c4bd6000: page_link=4018735808, offset=0, length=4096
[   50.384444] sgl[00000007] => c4bd4000: page_link=4018735744, offset=0, length=4096
[   50.392152] sgl[00000008] => c4b38000: page_link=4018730752, offset=0, length=4096
[   50.399846] sgl[00000009] => c5cfc000: page_link=4018876290, offset=0, length=4096
[   50.407485] 54nth call of ubi_ea_read_leb_sg
[   50.420878] sgl[00000000] => c5348000: page_link=4018796800, offset=0, length=4096
[   50.425301] sgl[00000001] => c677b000: page_link=4018962272, offset=0, length=4096
[   50.433072] sgl[00000002] => c441d000: page_link=4018672544, offset=0, length=4096
[   50.440781] sgl[00000003] => c4b1f000: page_link=4018729952, offset=0, length=4096
[   50.448486] sgl[00000004] => c4b0f000: page_link=4018729440, offset=0, length=4096
[   50.456121] sgl[00000005] => c5879000: page_link=4018839328, offset=0, length=4096
[   50.463826] sgl[00000006] => c59d8000: page_link=4018850560, offset=0, length=4096
[   50.471528] sgl[00000007] => c566c000: page_link=4018822528, offset=0, length=4096
[   50.479258] sgl[00000008] => c66e1000: page_link=4018957344, offset=0, length=4096
[   50.486894] sgl[00000009] => c53f0000: page_link=4018802176, offset=0, length=4096
[   50.494599] sgl[00000010] => c594e000: page_link=4018846146, offset=0, length=4096
realpath: /dev/disk/by-partuuid//dev/ubiblock0_2: No such file or directory
[   50.502309] 55nth call of ubi_ea_read_leb_sg
[   64.939917] sgl[00000000] => 00000000: page_link=4025764322, offset=0, length=512
[   64.944292] 56nth call of ubi_ea_read_leb_sg
[   64.952594] ==================================================================
[   64.964138] BUG: KASAN: null-ptr-deref in ubi_io_read+0xe8/0x41c
[   64.970203] Read of size 1 at addr 00000000 by task kworker/0:5/75
[   64.976416]
[   64.977930] CPU: 0 PID: 75 Comm: kworker/0:5 Not tainted 6.1.38 #1
[   64.984150] Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
[   64.990708] Workqueue: ubiblock0_2 ubiblock_do_work
[   64.995654]  unwind_backtrace from show_stack+0x10/0x14
[   65.000943]  show_stack from dump_stack_lvl+0x34/0x48
[   65.006063]  dump_stack_lvl from kasan_report+0xb8/0xe8
[   65.011350]  kasan_report from ubi_io_read+0xe8/0x41c
[   65.016453]  ubi_io_read from ubi_eba_read_leb+0x180/0x68c
[   65.021992]  ubi_eba_read_leb from ubi_eba_read_leb_sg+0x158/0x1fc
[   65.028229]  ubi_eba_read_leb_sg from ubi_leb_read_sg+0x8c/0xdc
[   65.034202]  ubi_leb_read_sg from ubiblock_do_work+0x194/0x428
[   65.040092]  ubiblock_do_work from process_one_work+0x46c/0x98c
[   65.046082]  process_one_work from worker_thread+0x7c/0x7a8
[   65.051718]  worker_thread from kthread+0x158/0x180
[   65.056659]  kthread from ret_from_fork+0x14/0x2c
[   65.061414] Exception stack(0xf0cabfb0 to 0xf0cabff8)
[   65.066504] bfa0:                                     00000000 00000000 00000000 00000000
[   65.074719] bfc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[   65.082933] bfe0: 00000000 00000000 00000000 00000000 00000013 00000000
[   65.089578] ==================================================================
[   65.097001] Disabling lock debugging due to kernel taint


> >> Did you print the LEB number, read length and offset in ubiblock_read()?
> >> Maybe there is a bug related to setting up the correct device geometry
> >> and the read request is off.
> > Here is some excerpt from another try with KASAN enabled and full debug output:
>
> Hm, we are within bounds. And looks like other reads worked.
>
> >  ==================================================================
> >  [  293.343675] BUG: KASAN: null-ptr-deref in ubi_io_read+0x1d4/0x46c
> >  [  293.349822] Read of size 1 at addr 00000000 by task kworker/0:3/18
> >  [  293.356037]
> >  [  293.357551] CPU: 0 PID: 18 Comm: kworker/0:3 Not tainted 6.1.36 #1
> >  [  293.363774] Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
> >  [  293.370331] Workqueue: ubiblock0_2 ubiblock_do_work
> >  [  293.375269]  unwind_backtrace from show_stack+0x10/0x14
> >  [  293.380557]  show_stack from dump_stack_lvl+0x34/0x48
> >  [  293.385668]  dump_stack_lvl from kasan_report+0xb8/0xe8
> >  [  293.390956]  kasan_report from ubi_io_read+0x1d4/0x46c
> >  [  293.396146]  ubi_io_read from ubi_eba_read_leb+0x3c4/0x5cc
> >  [  293.401686]  ubi_eba_read_leb from ubi_eba_read_leb_sg+0x84/0x1f8
> >  [  293.407831]  ubi_eba_read_leb_sg from ubi_leb_read_sg+0xb4/0x110
>
> Can you please double check whether the very first call to ubi_eba_read_leb_sg()
> fails or a later one?
As you can see in above logs, the first calls to ubi_eba_read_leb_sg() originate
from ubiblock_create(). Number 55 and 56 belong to read by cryptsetup.

>
> Thanks,
> //richard

Thanks
--
Stephan Wurm <stephan.wurm at a-eberle.de>



More information about the linux-mtd mailing list