[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 <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
15d99e02ba
commit
be33690d8f
|
@ -1001,7 +1001,15 @@ static inline int xfrm_policy_id2dir(u32 index)
|
|||
|
||||
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)
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue
Block a user