Message ID | 20210701022405.10817-6-digetx@gmail.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | Add OTG mode support to Tegra USB PHY, SMB347 and Nexus 7 | expand |
On Thu, Jul 01, 2021 at 05:23:58AM +0300, Dmitry Osipenko wrote: > The HNP work can be re-scheduled while it's still in-fly. This results in > re-initialization of the busy work, resetting the hrtimer's list node of > the work and crashing kernel with null dereference within kernel/timer > once work's timer is expired. It's very easy to trigger this problem by > re-plugging USB cable quickly. Initialize HNP work only once to fix this > trouble. [...] > - INIT_DELAYED_WORK(&fsm->hnp_polling_work, otg_hnp_polling_work); > + if (!fsm->hnp_work_inited) { > + INIT_DELAYED_WORK(&fsm->hnp_polling_work, otg_hnp_polling_work); > + fsm->hnp_work_inited = true; > + } > + Maybe you could just add an initialization function to be called by users of otg_fsm? It seems that only chipidea driver uses this struct currently. Best Regards Michał Mirosław
09.07.2021 01:42, Michał Mirosław пишет: > On Thu, Jul 01, 2021 at 05:23:58AM +0300, Dmitry Osipenko wrote: >> The HNP work can be re-scheduled while it's still in-fly. This results in >> re-initialization of the busy work, resetting the hrtimer's list node of >> the work and crashing kernel with null dereference within kernel/timer >> once work's timer is expired. It's very easy to trigger this problem by >> re-plugging USB cable quickly. Initialize HNP work only once to fix this >> trouble. > [...] >> - INIT_DELAYED_WORK(&fsm->hnp_polling_work, otg_hnp_polling_work); >> + if (!fsm->hnp_work_inited) { >> + INIT_DELAYED_WORK(&fsm->hnp_polling_work, otg_hnp_polling_work); >> + fsm->hnp_work_inited = true; >> + } >> + > > Maybe you could just add an initialization function to be called by > users of otg_fsm? It seems that only chipidea driver uses this > struct currently. If there are any out-of-tree users of the OTG FSM, then they will all get the fix too using the universal solution.
diff --git a/drivers/usb/common/usb-otg-fsm.c b/drivers/usb/common/usb-otg-fsm.c index 3740cf95560e..0697fde51d00 100644 --- a/drivers/usb/common/usb-otg-fsm.c +++ b/drivers/usb/common/usb-otg-fsm.c @@ -193,7 +193,11 @@ static void otg_start_hnp_polling(struct otg_fsm *fsm) if (!fsm->host_req_flag) return; - INIT_DELAYED_WORK(&fsm->hnp_polling_work, otg_hnp_polling_work); + if (!fsm->hnp_work_inited) { + INIT_DELAYED_WORK(&fsm->hnp_polling_work, otg_hnp_polling_work); + fsm->hnp_work_inited = true; + } + schedule_delayed_work(&fsm->hnp_polling_work, msecs_to_jiffies(T_HOST_REQ_POLL)); } diff --git a/include/linux/usb/otg-fsm.h b/include/linux/usb/otg-fsm.h index 3aee78dda16d..784659d4dc99 100644 --- a/include/linux/usb/otg-fsm.h +++ b/include/linux/usb/otg-fsm.h @@ -196,6 +196,7 @@ struct otg_fsm { struct mutex lock; u8 *host_req_flag; struct delayed_work hnp_polling_work; + bool hnp_work_inited; bool state_changed; };
The HNP work can be re-scheduled while it's still in-fly. This results in re-initialization of the busy work, resetting the hrtimer's list node of the work and crashing kernel with null dereference within kernel/timer once work's timer is expired. It's very easy to trigger this problem by re-plugging USB cable quickly. Initialize HNP work only once to fix this trouble. Cc: stable@vger.kernel.org Signed-off-by: Dmitry Osipenko <digetx@gmail.com> --- drivers/usb/common/usb-otg-fsm.c | 6 +++++- include/linux/usb/otg-fsm.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-)