lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Message-ID: <Pine.LNX.4.44L0.1409161046380.1166-100000@iolanthe.rowland.org> Date: Tue, 16 Sep 2014 11:32:14 -0400 (EDT) From: Alan Stern <stern@...land.harvard.edu> To: Petr Mládek <pmladek@...e.cz> cc: Greg Kroah-Hartman <gregkh@...uxfoundation.org>, Tejun Heo <tj@...nel.org>, Joe Lawrence <joe.lawrence@...atus.com>, Jiri Kosina <jkosina@...e.cz>, USB list <linux-usb@...r.kernel.org>, Kernel development list <linux-kernel@...r.kernel.org> Subject: Re: [PATCH 1/4] usb: hub: convert khubd into workqueue On Tue, 16 Sep 2014, Petr [iso-8859-1] Mládek wrote: > Anyway, the solution for the race between kick_hub_wq() and > hub_event() might be to get the reference already in kick_hub_wq(). Yes, this probably would work. > I mean something like: > > static void kick_hub_wq(struct usb_hub *hub) > { > if (hub->disconnected || work_pending(&hub->events)) > return; > /* > * Suppress autosuspend until the event is proceed. > * > * Be careful and make sure that the symmetric operation is > * always called. We are here only when there is no pending > * work for this hub. Therefore put the interface either when > * the new work is called or when it is canceled. > */ > usb_autopm_get_interface_no_resume(to_usb_interface(hub->intfdev)); > kref_get(&hub->kref); > > if (queue_work(hub_wq, &hub->events)) > return; > > /* the work could not be scheduled twice */ > kref_put(&hub->kref, hub_release); > usb_autopm_put_interface_no_suspend(intf); This should be usb_autopm_put_interface_async, not *_no_suspend, because you don't know at this point whether the runtime PM usage counter is > 1. (You do know it was > 1 at the time queue_work was called, but it may have changed since then.) > } > > And test for hub->disconnected at the very beginning of hub_event(). No, that's no good. The value isn't fully meaningful unless you are holding the device lock. That's why the test for hub->disconnected is placed where it is in hub_events. > Also we would need to put the reference when the work is canceled in > hub_disconnect(). You can't cancel the work in hub_disconnect. That's because cancelling a work item is always synchronous -- there's no cancel_work, only cancel_work_sync. This is okay; removing items from the hub_event_list was only a minor optimization anyway. There's no harm in letting the work item go ahead and run. > Hmm, I am not 100% sure if we could call > usb_autopm_get_interface_no_resume() without any lock here. > I guess so because otherwise the original code would not work. > The check for "hub->disconnected" would fail if the struct was freed > before the lock was taken. The caller of kick_khubd has to guarantee that the hub structure hasn't been deallocated. > It looks promissing. hub->intfdev is released together with "hub" in > hub_release(). Also it seems that kick_* and *disconnect functions > are called with some top level lock. For example, there is used dev > lock in drivers/usb/core/device.c. There's one more improvement you could make. It's not necessary to call usb_get_dev and usb_put_dev every time hub_events runs. Instead, we can call usb_get_dev once when the hub structure is created and usb_put_dev in hub_release. > > But you ignored what the comment says about "don't let it be added > > again". > > If we increase the reference in kick_hub_wq() and test > hub->disconnected at the very beginning of hub_event() it > should not cause real problem. In the worst case, it will release > struct usb_hub there instead of in hub_disconnect(). It already happens > with the original code in some circumstances. > > If you think that this is too tricky, I will put the lock back. It's probably okay without the lock. Please post an updated patch (just the first one in the series; the later ones will remain the same) with the changes discussed here so I can review it. Or better yet, rearrange the patch series. Make the first patch be the one that removes the useless loop in hub_events. That patch will be acceptable in any case, regardless of what happens with the workqueue change. Then the second patch can be the conversion to a workqueue. Alan Stern -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@...r.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists