Commit 8be987d73481831265d7e8c648bec838271bfd9b
Committed by
David S. Miller
1 parent
927606a17e
Exists in
master
and in
39 other branches
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
net/key/af_key.c
... | ... | @@ -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; |