Since xfrm_dev_{state,policy}_flush() are called from only NETDEV_DOWN and NETDEV_UNREGISTER events, making xfrm_dev_{state,policy}_flush() no-op by returning an error value from xfrm_dev_{state,policy}_flush_secctx_check() is pointless. Especially, if xfrm_dev_{state,policy}_flush_secctx_check() returned an error value upon NETDEV_UNREGISTER event, the system will hung up with unregister_netdevice: waiting for $dev to become free. Usage count = $count message because the reference to $dev acquired by xfrm_dev_{state,policy}_add() cannot be released. Signed-off-by: Tetsuo Handa --- net/xfrm/xfrm_policy.c | 35 ----------------------------------- net/xfrm/xfrm_state.c | 33 --------------------------------- 2 files changed, 68 deletions(-) diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 62486f866975..f4df6491095f 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -1778,41 +1778,12 @@ xfrm_policy_flush_secctx_check(struct net *net, u8 type, bool task_valid) } return err; } - -static inline int xfrm_dev_policy_flush_secctx_check(struct net *net, - struct net_device *dev, - bool task_valid) -{ - struct xfrm_policy *pol; - int err = 0; - - list_for_each_entry(pol, &net->xfrm.policy_all, walk.all) { - if (pol->walk.dead || - xfrm_policy_id2dir(pol->index) >= XFRM_POLICY_MAX || - pol->xdo.dev != dev) - continue; - - err = security_xfrm_policy_delete(pol->security); - if (err) { - xfrm_audit_policy_delete(pol, 0, task_valid); - return err; - } - } - return err; -} #else static inline int xfrm_policy_flush_secctx_check(struct net *net, u8 type, bool task_valid) { return 0; } - -static inline int xfrm_dev_policy_flush_secctx_check(struct net *net, - struct net_device *dev, - bool task_valid) -{ - return 0; -} #endif int xfrm_policy_flush(struct net *net, u8 type, bool task_valid) @@ -1861,11 +1832,6 @@ int xfrm_dev_policy_flush(struct net *net, struct net_device *dev, struct xfrm_policy *pol; spin_lock_bh(&net->xfrm.xfrm_policy_lock); - - err = xfrm_dev_policy_flush_secctx_check(net, dev, task_valid); - if (err) - goto out; - again: list_for_each_entry(pol, &net->xfrm.policy_all, walk.all) { if (pol->walk.dead) @@ -1888,7 +1854,6 @@ int xfrm_dev_policy_flush(struct net *net, struct net_device *dev, __xfrm_policy_inexact_flush(net); else err = -ESRCH; -out: spin_unlock_bh(&net->xfrm.xfrm_policy_lock); return err; } diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 98b362d51836..855778177558 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -881,41 +881,12 @@ xfrm_state_flush_secctx_check(struct net *net, u8 proto, bool task_valid) return err; } - -static inline int -xfrm_dev_state_flush_secctx_check(struct net *net, struct net_device *dev, bool task_valid) -{ - int i, err = 0; - - for (i = 0; i <= net->xfrm.state_hmask; i++) { - struct xfrm_state *x; - struct xfrm_dev_offload *xso; - - hlist_for_each_entry(x, net->xfrm.state_bydst+i, bydst) { - xso = &x->xso; - - if (xso->dev == dev && - (err = security_xfrm_state_delete(x)) != 0) { - xfrm_audit_state_delete(x, 0, task_valid); - return err; - } - } - } - - return err; -} #else static inline int xfrm_state_flush_secctx_check(struct net *net, u8 proto, bool task_valid) { return 0; } - -static inline int -xfrm_dev_state_flush_secctx_check(struct net *net, struct net_device *dev, bool task_valid) -{ - return 0; -} #endif int xfrm_state_flush(struct net *net, u8 proto, bool task_valid) @@ -966,9 +937,6 @@ int xfrm_dev_state_flush(struct net *net, struct net_device *dev, bool task_vali int i, err = 0, cnt = 0; spin_lock_bh(&net->xfrm.xfrm_state_lock); - err = xfrm_dev_state_flush_secctx_check(net, dev, task_valid); - if (err) - goto out; err = -ESRCH; for (i = 0; i <= net->xfrm.state_hmask; i++) { @@ -997,7 +965,6 @@ int xfrm_dev_state_flush(struct net *net, struct net_device *dev, bool task_vali if (cnt) err = 0; -out: spin_unlock_bh(&net->xfrm.xfrm_state_lock); spin_lock_bh(&xfrm_state_dev_gc_lock); -- 2.47.3