Patrick McHardy wrote: > Fix a regression in net-2.6.17 from the aevent patches. > > Protect references of xfrm_nl from outside of xfrm_user by RCU, check > that the socket is present in xfrm_aevent_is_on and set it to NULL > when unloading xfrm_user. > > static void __exit xfrm_user_exit(void) > { > xfrm_unregister_km(&netlink_mgr); > + rcu_assign_pointer(xfrm_nl, NULL); > + synchronize_rcu(); > sock_release(xfrm_nl->sk_socket); > } >
Sorry, thats just as broken as before. Better patch attached.
[XFRM]: Fix aevent related crash When xfrm_user isn't loaded xfrm_nl is NULL, which makes IPsec crash because xfrm_aevent_is_on passes the NULL pointer to netlink_has_listeners as socket. A second problem is that the xfrm_nl pointer is not cleared when the socket is releases at module unload time. Protect references of xfrm_nl from outside of xfrm_user by RCU, check that the socket is present in xfrm_aevent_is_on and set it to NULL when unloading xfrm_user. Signed-off-by: Patrick McHardy <[EMAIL PROTECTED]> --- commit 4b76213dc1378f874a64acd1c088d8e9a22759a1 tree d4fc2906ffcfa5afb0ad7f68bc861f0c1fb59cc8 parent 5134e9a6559778d2f3f8dcaf60a1009360e477a2 author Patrick McHardy <[EMAIL PROTECTED]> Mon, 06 Mar 2006 14:20:29 +0100 committer Patrick McHardy <[EMAIL PROTECTED]> Mon, 06 Mar 2006 14:20:29 +0100 include/net/xfrm.h | 10 +++++++++- net/xfrm/xfrm_user.c | 15 +++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 156f52e..7dff185 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1000,7 +1000,15 @@ static inline int xfrm_policy_id2dir(u32 static inline int xfrm_aevent_is_on(void) { - return netlink_has_listeners(xfrm_nl,XFRMNLGRP_AEVENTS); + struct sock *nlsk; + int ret = 0; + + rcu_read_lock(); + nlsk = rcu_dereference(xfrm_nl); + if (nlsk) + ret = netlink_has_listeners(nlsk, XFRMNLGRP_AEVENTS); + rcu_read_unlock(); + return ret; } static inline void xfrm_aevent_doreplay(struct xfrm_state *x) diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index ca8ac61..25c2fcf 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1947,12 +1947,15 @@ static struct xfrm_mgr netlink_mgr = { static int __init xfrm_user_init(void) { + struct sock *nlsk; + printk(KERN_INFO "Initializing IPsec netlink socket\n"); - xfrm_nl = netlink_kernel_create(NETLINK_XFRM, XFRMNLGRP_MAX, - xfrm_netlink_rcv, THIS_MODULE); - if (xfrm_nl == NULL) + nlsk = netlink_kernel_create(NETLINK_XFRM, XFRMNLGRP_MAX, + xfrm_netlink_rcv, THIS_MODULE); + if (nlsk == NULL) return -ENOMEM; + rcu_assign_pointer(xfrm_nl, nlsk); xfrm_register_km(&netlink_mgr); @@ -1961,8 +1964,12 @@ static int __init xfrm_user_init(void) static void __exit xfrm_user_exit(void) { + struct sock *nlsk = xfrm_nl; + xfrm_unregister_km(&netlink_mgr); - sock_release(xfrm_nl->sk_socket); + rcu_assign_pointer(xfrm_nl, NULL); + synchronize_rcu(); + sock_release(nlsk->sk_socket); } module_init(xfrm_user_init);