Commit 9e64cc9572b43afcbcd2d004538db435f2cd0587

Authored by Jamal Hadi Salim
Committed by David S. Miller
1 parent 8be987d734

xfrm: Flushing empty SAD generates false events

To see the effect make sure you have an empty SAD.
On window1 "ip xfrm mon" and on window2 issue "ip xfrm state 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 14 additions and 4 deletions Side-by-side Diff

... ... @@ -1768,8 +1768,11 @@
1768 1768 audit_info.secid = 0;
1769 1769 err = xfrm_state_flush(net, proto, &audit_info);
1770 1770 err2 = unicast_flush_resp(sk, hdr);
1771   - if (err || err2)
  1771 + if (err || err2) {
  1772 + if (err == -ESRCH) /* empty table - go quietly */
  1773 + err = 0;
1772 1774 return err ? err : err2;
  1775 + }
1773 1776  
1774 1777 c.data.proto = proto;
1775 1778 c.seq = hdr->sadb_msg_seq;
net/xfrm/xfrm_state.c
... ... @@ -603,13 +603,14 @@
603 603  
604 604 int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info)
605 605 {
606   - int i, err = 0;
  606 + int i, err = 0, cnt = 0;
607 607  
608 608 spin_lock_bh(&xfrm_state_lock);
609 609 err = xfrm_state_flush_secctx_check(net, proto, audit_info);
610 610 if (err)
611 611 goto out;
612 612  
  613 + err = -ESRCH;
613 614 for (i = 0; i <= net->xfrm.state_hmask; i++) {
614 615 struct hlist_node *entry;
615 616 struct xfrm_state *x;
616 617  
... ... @@ -626,13 +627,16 @@
626 627 audit_info->sessionid,
627 628 audit_info->secid);
628 629 xfrm_state_put(x);
  630 + if (!err)
  631 + cnt++;
629 632  
630 633 spin_lock_bh(&xfrm_state_lock);
631 634 goto restart;
632 635 }
633 636 }
634 637 }
635   - err = 0;
  638 + if (cnt)
  639 + err = 0;
636 640  
637 641 out:
638 642 spin_unlock_bh(&xfrm_state_lock);
net/xfrm/xfrm_user.c
... ... @@ -1524,8 +1524,11 @@
1524 1524 audit_info.sessionid = NETLINK_CB(skb).sessionid;
1525 1525 audit_info.secid = NETLINK_CB(skb).sid;
1526 1526 err = xfrm_state_flush(net, p->proto, &audit_info);
1527   - if (err)
  1527 + if (err) {
  1528 + if (err == -ESRCH) /* empty table */
  1529 + return 0;
1528 1530 return err;
  1531 + }
1529 1532 c.data.proto = p->proto;
1530 1533 c.event = nlh->nlmsg_type;
1531 1534 c.seq = nlh->nlmsg_seq;