Commit 2f1eb65f366b81aa3c22c31e6e8db26168777ec5

Authored by Jamal Hadi Salim
Committed by David S. Miller
1 parent 9e64cc9572

xfrm: Flushing empty SPD generates false events

To see the effect make sure you have an empty SPD.
On window1 "ip xfrm mon" and on window2 issue "ip xfrm policy flush"
You get prompt back in window2 and you see the flush event on window1.
With this fix, you still get prompt on window1 but no event on window2.

Thanks to Alexey Dobriyan for finding a bug in earlier version
when using pfkey to do the flushing.

Signed-off-by: Jamal Hadi Salim <hadi@cyberus.ca>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 3 changed files with 20 additions and 6 deletions Side-by-side Diff

... ... @@ -2735,8 +2735,11 @@
2735 2735 audit_info.secid = 0;
2736 2736 err = xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, &audit_info);
2737 2737 err2 = unicast_flush_resp(sk, hdr);
2738   - if (err || err2)
2739   - return err ? err : err2;
  2738 + if (err || err2) {
  2739 + if (err == -ESRCH) /* empty table - old silent behavior */
  2740 + return 0;
  2741 + return err;
  2742 + }
2740 2743  
2741 2744 c.data.type = XFRM_POLICY_TYPE_MAIN;
2742 2745 c.event = XFRM_MSG_FLUSHPOLICY;
net/xfrm/xfrm_policy.c
... ... @@ -771,7 +771,8 @@
771 771  
772 772 int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info)
773 773 {
774   - int dir, err = 0;
  774 + int dir, err = 0, cnt = 0;
  775 + struct xfrm_policy *dp;
775 776  
776 777 write_lock_bh(&xfrm_policy_lock);
777 778  
778 779  
... ... @@ -789,8 +790,10 @@
789 790 &net->xfrm.policy_inexact[dir], bydst) {
790 791 if (pol->type != type)
791 792 continue;
792   - __xfrm_policy_unlink(pol, dir);
  793 + dp = __xfrm_policy_unlink(pol, dir);
793 794 write_unlock_bh(&xfrm_policy_lock);
  795 + if (dp)
  796 + cnt++;
794 797  
795 798 xfrm_audit_policy_delete(pol, 1, audit_info->loginuid,
796 799 audit_info->sessionid,
797 800  
... ... @@ -809,8 +812,10 @@
809 812 bydst) {
810 813 if (pol->type != type)
811 814 continue;
812   - __xfrm_policy_unlink(pol, dir);
  815 + dp = __xfrm_policy_unlink(pol, dir);
813 816 write_unlock_bh(&xfrm_policy_lock);
  817 + if (dp)
  818 + cnt++;
814 819  
815 820 xfrm_audit_policy_delete(pol, 1,
816 821 audit_info->loginuid,
... ... @@ -824,6 +829,8 @@
824 829 }
825 830  
826 831 }
  832 + if (!cnt)
  833 + err = -ESRCH;
827 834 atomic_inc(&flow_cache_genid);
828 835 out:
829 836 write_unlock_bh(&xfrm_policy_lock);
net/xfrm/xfrm_user.c
... ... @@ -1679,8 +1679,12 @@
1679 1679 audit_info.sessionid = NETLINK_CB(skb).sessionid;
1680 1680 audit_info.secid = NETLINK_CB(skb).sid;
1681 1681 err = xfrm_policy_flush(net, type, &audit_info);
1682   - if (err)
  1682 + if (err) {
  1683 + if (err == -ESRCH) /* empty table */
  1684 + return 0;
1683 1685 return err;
  1686 + }
  1687 +
1684 1688 c.data.type = type;
1685 1689 c.event = nlh->nlmsg_type;
1686 1690 c.seq = nlh->nlmsg_seq;