Commit 8be987d73481831265d7e8c648bec838271bfd9b

Authored by Jamal Hadi Salim
Committed by David S. Miller
1 parent 927606a17e

pfkey: fix SA and SP flush sequence

RFC 2367 says flushing behavior should be:
1) user space -> kernel: flush
2) kernel: flush
3) kernel -> user space: flush event to ALL listeners

This is not realistic today in the presence of selinux policies
which may reject the flush etc. So we make the sequence become:
1) user space -> kernel: flush
2) kernel: flush
3) kernel -> user space: flush response to originater from #1
4) if there were no errors then:
kernel -> user space: flush event to ALL listeners

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

Showing 1 changed file with 27 additions and 6 deletions Side-by-side Diff

... ... @@ -1712,6 +1712,23 @@
1712 1712 return 0;
1713 1713 }
1714 1714  
  1715 +static int unicast_flush_resp(struct sock *sk, struct sadb_msg *ihdr)
  1716 +{
  1717 + struct sk_buff *skb;
  1718 + struct sadb_msg *hdr;
  1719 +
  1720 + skb = alloc_skb(sizeof(struct sadb_msg) + 16, GFP_ATOMIC);
  1721 + if (!skb)
  1722 + return -ENOBUFS;
  1723 +
  1724 + hdr = (struct sadb_msg *) skb_put(skb, sizeof(struct sadb_msg));
  1725 + memcpy(hdr, ihdr, sizeof(struct sadb_msg));
  1726 + hdr->sadb_msg_errno = (uint8_t) 0;
  1727 + hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
  1728 +
  1729 + return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ONE, sk, sock_net(sk));
  1730 +}
  1731 +
1715 1732 static int key_notify_sa_flush(struct km_event *c)
1716 1733 {
1717 1734 struct sk_buff *skb;
... ... @@ -1740,7 +1757,7 @@
1740 1757 unsigned proto;
1741 1758 struct km_event c;
1742 1759 struct xfrm_audit audit_info;
1743   - int err;
  1760 + int err, err2;
1744 1761  
1745 1762 proto = pfkey_satype2proto(hdr->sadb_msg_satype);
1746 1763 if (proto == 0)
... ... @@ -1750,8 +1767,10 @@
1750 1767 audit_info.sessionid = audit_get_sessionid(current);
1751 1768 audit_info.secid = 0;
1752 1769 err = xfrm_state_flush(net, proto, &audit_info);
1753   - if (err)
1754   - return err;
  1770 + err2 = unicast_flush_resp(sk, hdr);
  1771 + if (err || err2)
  1772 + return err ? err : err2;
  1773 +
1755 1774 c.data.proto = proto;
1756 1775 c.seq = hdr->sadb_msg_seq;
1757 1776 c.pid = hdr->sadb_msg_pid;
1758 1777  
... ... @@ -2706,14 +2725,16 @@
2706 2725 struct net *net = sock_net(sk);
2707 2726 struct km_event c;
2708 2727 struct xfrm_audit audit_info;
2709   - int err;
  2728 + int err, err2;
2710 2729  
2711 2730 audit_info.loginuid = audit_get_loginuid(current);
2712 2731 audit_info.sessionid = audit_get_sessionid(current);
2713 2732 audit_info.secid = 0;
2714 2733 err = xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, &audit_info);
2715   - if (err)
2716   - return err;
  2734 + err2 = unicast_flush_resp(sk, hdr);
  2735 + if (err || err2)
  2736 + return err ? err : err2;
  2737 +
2717 2738 c.data.type = XFRM_POLICY_TYPE_MAIN;
2718 2739 c.event = XFRM_MSG_FLUSHPOLICY;
2719 2740 c.pid = hdr->sadb_msg_pid;