Bluetooth: bnep: Fix module reference
We cannot call module_put(THIS_MODULE) if this is our last reference. Otherwise, this call may cleanup our module before it returns. Gladly, the kthread API provides a simple wrapper for us. So lets use module_put_and_exit() to avoid a race condition with the module cleanup code. Signed-off-by: David Herrmann <dh.herrmann@googlemail.com> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
This commit is contained in:
Родитель
48b28b8db9
Коммит
9b338c3dd1
|
@ -79,17 +79,12 @@ static struct bnep_session *__bnep_get_session(u8 *dst)
|
||||||
|
|
||||||
static void __bnep_link_session(struct bnep_session *s)
|
static void __bnep_link_session(struct bnep_session *s)
|
||||||
{
|
{
|
||||||
/* It's safe to call __module_get() here because sessions are added
|
|
||||||
by the socket layer which has to hold the reference to this module.
|
|
||||||
*/
|
|
||||||
__module_get(THIS_MODULE);
|
|
||||||
list_add(&s->list, &bnep_session_list);
|
list_add(&s->list, &bnep_session_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __bnep_unlink_session(struct bnep_session *s)
|
static void __bnep_unlink_session(struct bnep_session *s)
|
||||||
{
|
{
|
||||||
list_del(&s->list);
|
list_del(&s->list);
|
||||||
module_put(THIS_MODULE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bnep_send(struct bnep_session *s, void *data, size_t len)
|
static int bnep_send(struct bnep_session *s, void *data, size_t len)
|
||||||
|
@ -530,6 +525,7 @@ static int bnep_session(void *arg)
|
||||||
|
|
||||||
up_write(&bnep_session_sem);
|
up_write(&bnep_session_sem);
|
||||||
free_netdev(dev);
|
free_netdev(dev);
|
||||||
|
module_put_and_exit(0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -616,9 +612,11 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
|
||||||
|
|
||||||
__bnep_link_session(s);
|
__bnep_link_session(s);
|
||||||
|
|
||||||
|
__module_get(THIS_MODULE);
|
||||||
s->task = kthread_run(bnep_session, s, "kbnepd %s", dev->name);
|
s->task = kthread_run(bnep_session, s, "kbnepd %s", dev->name);
|
||||||
if (IS_ERR(s->task)) {
|
if (IS_ERR(s->task)) {
|
||||||
/* Session thread start failed, gotta cleanup. */
|
/* Session thread start failed, gotta cleanup. */
|
||||||
|
module_put(THIS_MODULE);
|
||||||
unregister_netdev(dev);
|
unregister_netdev(dev);
|
||||||
__bnep_unlink_session(s);
|
__bnep_unlink_session(s);
|
||||||
err = PTR_ERR(s->task);
|
err = PTR_ERR(s->task);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче