diff options
author | Jamal Hadi Salim <hadi@cyberus.ca> | 2010-02-18 21:00:40 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-02-19 16:11:49 -0500 |
commit | 8be987d73481831265d7e8c648bec838271bfd9b (patch) | |
tree | d06242ca463d87e3840090959c695d9c1a151799 /net/key/af_key.c | |
parent | 927606a17e802fcf0c9ee82a74bc444b84726e67 (diff) |
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>
Diffstat (limited to 'net/key/af_key.c')
-rw-r--r-- | net/key/af_key.c | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/net/key/af_key.c b/net/key/af_key.c index 79d2c0f3c334..b3faede9a4f6 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
@@ -1712,6 +1712,23 @@ static int pfkey_register(struct sock *sk, struct sk_buff *skb, struct sadb_msg | |||
1712 | return 0; | 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 | static int key_notify_sa_flush(struct km_event *c) | 1732 | static int key_notify_sa_flush(struct km_event *c) |
1716 | { | 1733 | { |
1717 | struct sk_buff *skb; | 1734 | struct sk_buff *skb; |
@@ -1740,7 +1757,7 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd | |||
1740 | unsigned proto; | 1757 | unsigned proto; |
1741 | struct km_event c; | 1758 | struct km_event c; |
1742 | struct xfrm_audit audit_info; | 1759 | struct xfrm_audit audit_info; |
1743 | int err; | 1760 | int err, err2; |
1744 | 1761 | ||
1745 | proto = pfkey_satype2proto(hdr->sadb_msg_satype); | 1762 | proto = pfkey_satype2proto(hdr->sadb_msg_satype); |
1746 | if (proto == 0) | 1763 | if (proto == 0) |
@@ -1750,8 +1767,10 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd | |||
1750 | audit_info.sessionid = audit_get_sessionid(current); | 1767 | audit_info.sessionid = audit_get_sessionid(current); |
1751 | audit_info.secid = 0; | 1768 | audit_info.secid = 0; |
1752 | err = xfrm_state_flush(net, proto, &audit_info); | 1769 | err = xfrm_state_flush(net, proto, &audit_info); |
1753 | if (err) | 1770 | err2 = unicast_flush_resp(sk, hdr); |
1754 | return err; | 1771 | if (err || err2) |
1772 | return err ? err : err2; | ||
1773 | |||
1755 | c.data.proto = proto; | 1774 | c.data.proto = proto; |
1756 | c.seq = hdr->sadb_msg_seq; | 1775 | c.seq = hdr->sadb_msg_seq; |
1757 | c.pid = hdr->sadb_msg_pid; | 1776 | c.pid = hdr->sadb_msg_pid; |
@@ -2706,14 +2725,16 @@ static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg | |||
2706 | struct net *net = sock_net(sk); | 2725 | struct net *net = sock_net(sk); |
2707 | struct km_event c; | 2726 | struct km_event c; |
2708 | struct xfrm_audit audit_info; | 2727 | struct xfrm_audit audit_info; |
2709 | int err; | 2728 | int err, err2; |
2710 | 2729 | ||
2711 | audit_info.loginuid = audit_get_loginuid(current); | 2730 | audit_info.loginuid = audit_get_loginuid(current); |
2712 | audit_info.sessionid = audit_get_sessionid(current); | 2731 | audit_info.sessionid = audit_get_sessionid(current); |
2713 | audit_info.secid = 0; | 2732 | audit_info.secid = 0; |
2714 | err = xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, &audit_info); | 2733 | err = xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, &audit_info); |
2715 | if (err) | 2734 | err2 = unicast_flush_resp(sk, hdr); |
2716 | return err; | 2735 | if (err || err2) |
2736 | return err ? err : err2; | ||
2737 | |||
2717 | c.data.type = XFRM_POLICY_TYPE_MAIN; | 2738 | c.data.type = XFRM_POLICY_TYPE_MAIN; |
2718 | c.event = XFRM_MSG_FLUSHPOLICY; | 2739 | c.event = XFRM_MSG_FLUSHPOLICY; |
2719 | c.pid = hdr->sadb_msg_pid; | 2740 | c.pid = hdr->sadb_msg_pid; |