Skip to content

Commit

Permalink
staging: erofs: fix use-after-free of on-stack `z_erofs_vle_unzip_io'
Browse files Browse the repository at this point in the history
[ Upstream commit 848bd9acdcd00c164b42b14aacec242949ecd471 ]

The root cause is the race as follows:
 Thread #0                         Thread #1

 z_erofs_vle_unzip_kickoff         z_erofs_submit_and_unzip

                                    struct z_erofs_vle_unzip_io io[]
   atomic_add_return()
                                    wait_event()
                                    [end of function]
   wake_up()

Fix it by taking the waitqueue lock between atomic_add_return and
wake_up to close such the race.

kernel message:

Unable to handle kernel paging request at virtual address 97f7052caa1303dc
...
Workqueue: kverityd verity_work
task: ffffffe32bcb8000 task.stack: ffffffe3298a0000
PC is at __wake_up_common+0x48/0xa8
LR is at __wake_up+0x3c/0x58
...
Call trace:
...
[<ffffff94a08ff648>] __wake_up_common+0x48/0xa8
[<ffffff94a08ff8b8>] __wake_up+0x3c/0x58
[<ffffff94a0c11b60>] z_erofs_vle_unzip_kickoff+0x40/0x64
[<ffffff94a0c118e4>] z_erofs_vle_read_endio+0x94/0x134
[<ffffff94a0c83c9c>] bio_endio+0xe4/0xf8
[<ffffff94a1076540>] dec_pending+0x134/0x32c
[<ffffff94a1076f28>] clone_endio+0x90/0xf4
[<ffffff94a0c83c9c>] bio_endio+0xe4/0xf8
[<ffffff94a1095024>] verity_work+0x210/0x368
[<ffffff94a08c4150>] process_one_work+0x188/0x4b4
[<ffffff94a08c45bc>] worker_thread+0x140/0x458
[<ffffff94a08cad48>] kthread+0xec/0x108
[<ffffff94a0883ab4>] ret_from_fork+0x10/0x1c
Code: d1006273 54000260 f9400804 b9400019 (b85fc081)
---[ end trace be9dde154f677cd1 ]---

Reviewed-by: Chao Yu <[email protected]>
Signed-off-by: Gao Xiang <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

Signed-off-by: Sasha Levin <[email protected]>
Signed-off-by: Cyber Knight <[email protected]>
Signed-off-by: Edwiin Kusuma Jaya <[email protected]>
  • Loading branch information
Gao Xiang authored and kutemeikito committed Sep 25, 2024
1 parent e7da907 commit 5bc1f3b
Showing 1 changed file with 9 additions and 4 deletions.
13 changes: 9 additions & 4 deletions drivers/staging/erofs/unzip_vle.c
Original file line number Diff line number Diff line change
Expand Up @@ -724,13 +724,18 @@ static void z_erofs_vle_unzip_kickoff(void *ptr, int bios)
struct z_erofs_vle_unzip_io *io = tagptr_unfold_ptr(t);
bool background = tagptr_unfold_tags(t);

if (atomic_add_return(bios, &io->pending_bios))
if (!background) {
unsigned long flags;

spin_lock_irqsave(&io->u.wait.lock, flags);
if (!atomic_add_return(bios, &io->pending_bios))
wake_up_locked(&io->u.wait);
spin_unlock_irqrestore(&io->u.wait.lock, flags);
return;
}

if (background)
if (!atomic_add_return(bios, &io->pending_bios))
queue_work(z_erofs_workqueue, &io->u.work);
else
wake_up(&io->u.wait);
}

static inline void z_erofs_vle_read_endio(struct bio *bio)
Expand Down

0 comments on commit 5bc1f3b

Please sign in to comment.