| From b292b50b0efcc7095d8bf15505fba6909bb35dce Mon Sep 17 00:00:00 2001 |
| From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> |
| Date: Mon, 13 Jul 2020 11:12:54 +0900 |
| Subject: driver core: Fix probe_count imbalance in really_probe() |
| |
| From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> |
| |
| commit b292b50b0efcc7095d8bf15505fba6909bb35dce upstream. |
| |
| syzbot is reporting hung task in wait_for_device_probe() [1]. At least, |
| we always need to decrement probe_count if we incremented probe_count in |
| really_probe(). |
| |
| However, since I can't find "Resources present before probing" message in |
| the console log, both "this message simply flowed off" and "syzbot is not |
| hitting this path" will be possible. Therefore, while we are at it, let's |
| also prepare for concurrent wait_for_device_probe() calls by replacing |
| wake_up() with wake_up_all(). |
| |
| [1] https://syzkaller.appspot.com/bug?id=25c833f1983c9c1d512f4ff860dd0d7f5a2e2c0f |
| |
| Reported-by: syzbot <syzbot+805f5f6ae37411f15b64@syzkaller.appspotmail.com> |
| Fixes: 7c35e699c88bd607 ("driver core: Print device when resources present in really_probe()") |
| Cc: Geert Uytterhoeven <geert+renesas@glider.be> |
| Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> |
| Cc: stable <stable@kernel.org> |
| Link: https://lore.kernel.org/r/20200713021254.3444-1-penguin-kernel@I-love.SAKURA.ne.jp |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| |
| --- |
| drivers/base/dd.c | 7 ++++--- |
| 1 file changed, 4 insertions(+), 3 deletions(-) |
| |
| --- a/drivers/base/dd.c |
| +++ b/drivers/base/dd.c |
| @@ -276,7 +276,7 @@ static void deferred_probe_timeout_work_ |
| |
| list_for_each_entry_safe(private, p, &deferred_probe_pending_list, deferred_probe) |
| dev_info(private->device, "deferred probe pending"); |
| - wake_up(&probe_timeout_waitqueue); |
| + wake_up_all(&probe_timeout_waitqueue); |
| } |
| static DECLARE_DELAYED_WORK(deferred_probe_timeout_work, deferred_probe_timeout_work_func); |
| |
| @@ -487,7 +487,8 @@ static int really_probe(struct device *d |
| drv->bus->name, __func__, drv->name, dev_name(dev)); |
| if (!list_empty(&dev->devres_head)) { |
| dev_crit(dev, "Resources present before probing\n"); |
| - return -EBUSY; |
| + ret = -EBUSY; |
| + goto done; |
| } |
| |
| re_probe: |
| @@ -608,7 +609,7 @@ pinctrl_bind_failed: |
| ret = 0; |
| done: |
| atomic_dec(&probe_count); |
| - wake_up(&probe_waitqueue); |
| + wake_up_all(&probe_waitqueue); |
| return ret; |
| } |
| |