Commit d71ffeb1 authored by David Woodhouse's avatar David Woodhouse

br2684: fix module_put() race

The br2684 code used module_put() during unassignment from vcc with
hope that we have BKL. This assumption is no longer true.

Now owner field in atmvcc is used to move this module_put()
to vcc_destroy_socket().
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
Acked-by: default avatarKrzysztof Mazur <krzysiek@podlesie.net>
parent 0e56d99a
...@@ -69,6 +69,7 @@ struct br2684_vcc { ...@@ -69,6 +69,7 @@ struct br2684_vcc {
void (*old_push)(struct atm_vcc *vcc, struct sk_buff *skb); void (*old_push)(struct atm_vcc *vcc, struct sk_buff *skb);
void (*old_pop)(struct atm_vcc *vcc, struct sk_buff *skb); void (*old_pop)(struct atm_vcc *vcc, struct sk_buff *skb);
void (*old_release_cb)(struct atm_vcc *vcc); void (*old_release_cb)(struct atm_vcc *vcc);
struct module *old_owner;
enum br2684_encaps encaps; enum br2684_encaps encaps;
struct list_head brvccs; struct list_head brvccs;
#ifdef CONFIG_ATM_BR2684_IPFILTER #ifdef CONFIG_ATM_BR2684_IPFILTER
...@@ -414,8 +415,8 @@ static void br2684_close_vcc(struct br2684_vcc *brvcc) ...@@ -414,8 +415,8 @@ static void br2684_close_vcc(struct br2684_vcc *brvcc)
brvcc->atmvcc->user_back = NULL; /* what about vcc->recvq ??? */ brvcc->atmvcc->user_back = NULL; /* what about vcc->recvq ??? */
brvcc->atmvcc->release_cb = brvcc->old_release_cb; brvcc->atmvcc->release_cb = brvcc->old_release_cb;
brvcc->old_push(brvcc->atmvcc, NULL); /* pass on the bad news */ brvcc->old_push(brvcc->atmvcc, NULL); /* pass on the bad news */
module_put(brvcc->old_owner);
kfree(brvcc); kfree(brvcc);
module_put(THIS_MODULE);
} }
/* when AAL5 PDU comes in: */ /* when AAL5 PDU comes in: */
...@@ -590,10 +591,12 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg) ...@@ -590,10 +591,12 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg)
brvcc->old_push = atmvcc->push; brvcc->old_push = atmvcc->push;
brvcc->old_pop = atmvcc->pop; brvcc->old_pop = atmvcc->pop;
brvcc->old_release_cb = atmvcc->release_cb; brvcc->old_release_cb = atmvcc->release_cb;
brvcc->old_owner = atmvcc->owner;
barrier(); barrier();
atmvcc->push = br2684_push; atmvcc->push = br2684_push;
atmvcc->pop = br2684_pop; atmvcc->pop = br2684_pop;
atmvcc->release_cb = br2684_release_cb; atmvcc->release_cb = br2684_release_cb;
atmvcc->owner = THIS_MODULE;
/* initialize netdev carrier state */ /* initialize netdev carrier state */
if (atmvcc->dev->signal == ATM_PHY_SIG_LOST) if (atmvcc->dev->signal == ATM_PHY_SIG_LOST)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment