usb: f_fs: Prevent race between ep0_release & reset_work
When ffs_func_disable is called the driver will call set_alt
as part of which if FFS_DEACTIVATED is set then it schedules
reset_work. It further goes and tries to call epfile_destroy
where kfree is done. If within the same time, if ep0_release
is also called, it will also go forward and call epfiles_destroy.
This is because although the driver did kfree, but did't mark NULL,
which is why the if check for epfile equals NULL will fail to prevent
and will still be able to proceed. At this point the epfile instance
is corrupted therefore when in epfile_destroy it goes into the if
check which will trigger the BUG_ON check causing crash.
Following is the illustration:
CPU1 CPU2
ffs_ep0_release
ffs_data_closed
ffs->state = FFS_DEACTIVATED (atomic context)
ffs_func_disable
ffs_func_set_alt
schedule_work(&ffs->reset_work)
ffs_epfiles_destroy(ffs->epfiles)
(running for loop not finished)
ffs_reset_work (preempts)
ffs_data_reset
ffs_data_clear
ffs_epfiles_destroy(ffs->epfiles)
Fix this by protecting the epfile_destroy calls with mutex_lock
and also ensuring to mark epfiles NULL within it.
Signed-off-by: Udipto Goswami <ugoswami@codeaurora.org>
Bug: 183548358
Bug: 199146484
Bug: 203790673
Test: build, boot
Signed-off-by: Jimmy Hu <hhhuuu@google.com>
Signed-off-by: Peggy Chan <peichi@google.com>
Change-Id: I3f560014314d10ea1e42965290d7fbf00018dd7c
1 file changed