diff options
author | Alexey Dobriyan <adobriyan@gmail.com> | 2010-01-29 21:53:27 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-02-03 21:11:11 -0500 |
commit | 180211b841b5bf13ab10d19202adab3eb7749f6c (patch) | |
tree | eeb1a2a2136e03a4a38dc09d26b8dd83b47994c9 /net | |
parent | f98bfbd78c37c5946cc53089da32a5f741efdeb7 (diff) |
af_key: fix netns ops ordering on module load/unload
1. After sock_register() returns, it's possible to create sockets,
even if module still not initialized fully (blame generic module code
for that!)
2. Consequently, pfkey_create() can be called with pfkey_net_id still not
initialized which will BUG_ON in net_generic():
kernel BUG at include/net/netns/generic.h:43!
3. During netns shutdown, netns ops should be unregistered after
key manager unregistered because key manager calls can be triggered
from xfrm_user module:
general protection fault: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC
pfkey_broadcast+0x111/0x210 [af_key]
pfkey_send_notify+0x16a/0x300 [af_key]
km_state_notify+0x41/0x70
xfrm_flush_sa+0x75/0x90 [xfrm_user]
4. Unregister netns ops after socket ops just in case and for symmetry.
Reported by Luca Tettamanti.
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Tested-by: Luca Tettamanti <kronos.it@gmail.com>
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/key/af_key.c | 15 |
1 files changed, 8 insertions, 7 deletions
diff --git a/net/key/af_key.c b/net/key/af_key.c index 76fa6fef6473..539f43bc97db 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
@@ -3794,9 +3794,9 @@ static struct pernet_operations pfkey_net_ops = { | |||
3794 | 3794 | ||
3795 | static void __exit ipsec_pfkey_exit(void) | 3795 | static void __exit ipsec_pfkey_exit(void) |
3796 | { | 3796 | { |
3797 | unregister_pernet_subsys(&pfkey_net_ops); | ||
3798 | xfrm_unregister_km(&pfkeyv2_mgr); | 3797 | xfrm_unregister_km(&pfkeyv2_mgr); |
3799 | sock_unregister(PF_KEY); | 3798 | sock_unregister(PF_KEY); |
3799 | unregister_pernet_subsys(&pfkey_net_ops); | ||
3800 | proto_unregister(&key_proto); | 3800 | proto_unregister(&key_proto); |
3801 | } | 3801 | } |
3802 | 3802 | ||
@@ -3807,21 +3807,22 @@ static int __init ipsec_pfkey_init(void) | |||
3807 | if (err != 0) | 3807 | if (err != 0) |
3808 | goto out; | 3808 | goto out; |
3809 | 3809 | ||
3810 | err = sock_register(&pfkey_family_ops); | 3810 | err = register_pernet_subsys(&pfkey_net_ops); |
3811 | if (err != 0) | 3811 | if (err != 0) |
3812 | goto out_unregister_key_proto; | 3812 | goto out_unregister_key_proto; |
3813 | err = sock_register(&pfkey_family_ops); | ||
3814 | if (err != 0) | ||
3815 | goto out_unregister_pernet; | ||
3813 | err = xfrm_register_km(&pfkeyv2_mgr); | 3816 | err = xfrm_register_km(&pfkeyv2_mgr); |
3814 | if (err != 0) | 3817 | if (err != 0) |
3815 | goto out_sock_unregister; | 3818 | goto out_sock_unregister; |
3816 | err = register_pernet_subsys(&pfkey_net_ops); | ||
3817 | if (err != 0) | ||
3818 | goto out_xfrm_unregister_km; | ||
3819 | out: | 3819 | out: |
3820 | return err; | 3820 | return err; |
3821 | out_xfrm_unregister_km: | 3821 | |
3822 | xfrm_unregister_km(&pfkeyv2_mgr); | ||
3823 | out_sock_unregister: | 3822 | out_sock_unregister: |
3824 | sock_unregister(PF_KEY); | 3823 | sock_unregister(PF_KEY); |
3824 | out_unregister_pernet: | ||
3825 | unregister_pernet_subsys(&pfkey_net_ops); | ||
3825 | out_unregister_key_proto: | 3826 | out_unregister_key_proto: |
3826 | proto_unregister(&key_proto); | 3827 | proto_unregister(&key_proto); |
3827 | goto out; | 3828 | goto out; |