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 | |
| 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')
| -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; |
