* [PATCH 0/3] pfkey/xfrm SAD/SPD flushing fixes [not found] <flush-fix-xfrm> @ 2010-02-19 12:00 ` jamal 2010-02-19 12:00 ` [PATCH 1/3] pfkey: fix SA and SP flush sequence jamal 2010-02-19 21:12 ` [PATCH 0/3] pfkey/xfrm SAD/SPD flushing fixes David Miller 0 siblings, 2 replies; 5+ messages in thread From: jamal @ 2010-02-19 12:00 UTC (permalink / raw) To: davem, adobriyan; +Cc: netdev, Jamal Hadi Salim From: Jamal Hadi Salim <hadi@cyberus.ca> This patch set does split for pfkey response for flushing and makes sure events for flush are generated only when we have a non-empty SAD/SPD. We maintain current behavior of silence when a table is empty. Jamal Hadi Salim (3): pfkey: fix SA and SP flush sequence xfrm: Flushing empty SAD generates false events xfrm: Flushing empty SPD generates false events net/key/af_key.c | 37 ++++++++++++++++++++++++++++++++----- net/xfrm/xfrm_policy.c | 13 ++++++++++--- net/xfrm/xfrm_state.c | 8 ++++++-- net/xfrm/xfrm_user.c | 11 +++++++++-- 4 files changed, 57 insertions(+), 12 deletions(-) ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/3] pfkey: fix SA and SP flush sequence 2010-02-19 12:00 ` [PATCH 0/3] pfkey/xfrm SAD/SPD flushing fixes jamal @ 2010-02-19 12:00 ` jamal 2010-02-19 12:00 ` [PATCH 2/3] xfrm: Flushing empty SAD generates false events jamal 2010-02-19 21:12 ` [PATCH 0/3] pfkey/xfrm SAD/SPD flushing fixes David Miller 1 sibling, 1 reply; 5+ messages in thread From: jamal @ 2010-02-19 12:00 UTC (permalink / raw) To: davem, adobriyan; +Cc: netdev, Jamal Hadi Salim From: Jamal Hadi Salim <hadi@cyberus.ca> 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> --- 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 79d2c0f..b3faede 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 return 0; } +static int unicast_flush_resp(struct sock *sk, struct sadb_msg *ihdr) +{ + struct sk_buff *skb; + struct sadb_msg *hdr; + + skb = alloc_skb(sizeof(struct sadb_msg) + 16, GFP_ATOMIC); + if (!skb) + return -ENOBUFS; + + hdr = (struct sadb_msg *) skb_put(skb, sizeof(struct sadb_msg)); + memcpy(hdr, ihdr, sizeof(struct sadb_msg)); + hdr->sadb_msg_errno = (uint8_t) 0; + hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); + + return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ONE, sk, sock_net(sk)); +} + static int key_notify_sa_flush(struct km_event *c) { struct sk_buff *skb; @@ -1740,7 +1757,7 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd unsigned proto; struct km_event c; struct xfrm_audit audit_info; - int err; + int err, err2; proto = pfkey_satype2proto(hdr->sadb_msg_satype); if (proto == 0) @@ -1750,8 +1767,10 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd audit_info.sessionid = audit_get_sessionid(current); audit_info.secid = 0; err = xfrm_state_flush(net, proto, &audit_info); - if (err) - return err; + err2 = unicast_flush_resp(sk, hdr); + if (err || err2) + return err ? err : err2; + c.data.proto = proto; c.seq = hdr->sadb_msg_seq; c.pid = hdr->sadb_msg_pid; @@ -2706,14 +2725,16 @@ static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg struct net *net = sock_net(sk); struct km_event c; struct xfrm_audit audit_info; - int err; + int err, err2; audit_info.loginuid = audit_get_loginuid(current); audit_info.sessionid = audit_get_sessionid(current); audit_info.secid = 0; err = xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, &audit_info); - if (err) - return err; + err2 = unicast_flush_resp(sk, hdr); + if (err || err2) + return err ? err : err2; + c.data.type = XFRM_POLICY_TYPE_MAIN; c.event = XFRM_MSG_FLUSHPOLICY; c.pid = hdr->sadb_msg_pid; -- 1.6.0.4 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/3] xfrm: Flushing empty SAD generates false events 2010-02-19 12:00 ` [PATCH 1/3] pfkey: fix SA and SP flush sequence jamal @ 2010-02-19 12:00 ` jamal 2010-02-19 12:00 ` [PATCH 3/3] xfrm: Flushing empty SPD " jamal 0 siblings, 1 reply; 5+ messages in thread From: jamal @ 2010-02-19 12:00 UTC (permalink / raw) To: davem, adobriyan; +Cc: netdev, Jamal Hadi Salim From: Jamal Hadi Salim <hadi@cyberus.ca> 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> --- net/key/af_key.c | 5 ++++- net/xfrm/xfrm_state.c | 8 ++++++-- net/xfrm/xfrm_user.c | 5 ++++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/net/key/af_key.c b/net/key/af_key.c index b3faede..c269ce6 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1768,8 +1768,11 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd audit_info.secid = 0; err = xfrm_state_flush(net, proto, &audit_info); err2 = unicast_flush_resp(sk, hdr); - if (err || err2) + if (err || err2) { + if (err == -ESRCH) /* empty table - go quietly */ + err = 0; return err ? err : err2; + } c.data.proto = proto; c.seq = hdr->sadb_msg_seq; diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index c9d6a5f..9fa3322 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -603,13 +603,14 @@ xfrm_state_flush_secctx_check(struct net *net, u8 proto, struct xfrm_audit *audi int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info) { - int i, err = 0; + int i, err = 0, cnt = 0; spin_lock_bh(&xfrm_state_lock); err = xfrm_state_flush_secctx_check(net, proto, audit_info); if (err) goto out; + err = -ESRCH; for (i = 0; i <= net->xfrm.state_hmask; i++) { struct hlist_node *entry; struct xfrm_state *x; @@ -626,13 +627,16 @@ restart: audit_info->sessionid, audit_info->secid); xfrm_state_put(x); + if (!err) + cnt++; spin_lock_bh(&xfrm_state_lock); goto restart; } } } - err = 0; + if (cnt) + err = 0; out: spin_unlock_bh(&xfrm_state_lock); diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 943c871..cd94a9d 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1524,8 +1524,11 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, audit_info.sessionid = NETLINK_CB(skb).sessionid; audit_info.secid = NETLINK_CB(skb).sid; err = xfrm_state_flush(net, p->proto, &audit_info); - if (err) + if (err) { + if (err == -ESRCH) /* empty table */ + return 0; return err; + } c.data.proto = p->proto; c.event = nlh->nlmsg_type; c.seq = nlh->nlmsg_seq; -- 1.6.0.4 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 3/3] xfrm: Flushing empty SPD generates false events 2010-02-19 12:00 ` [PATCH 2/3] xfrm: Flushing empty SAD generates false events jamal @ 2010-02-19 12:00 ` jamal 0 siblings, 0 replies; 5+ messages in thread From: jamal @ 2010-02-19 12:00 UTC (permalink / raw) To: davem, adobriyan; +Cc: netdev, Jamal Hadi Salim From: Jamal Hadi Salim <hadi@cyberus.ca> To see the effect make sure you have an empty SPD. On window1 "ip xfrm mon" and on window2 issue "ip xfrm policy 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> --- net/key/af_key.c | 7 +++++-- net/xfrm/xfrm_policy.c | 13 ++++++++++--- net/xfrm/xfrm_user.c | 6 +++++- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/net/key/af_key.c b/net/key/af_key.c index c269ce6..a20d2fa 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -2735,8 +2735,11 @@ static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg audit_info.secid = 0; err = xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, &audit_info); err2 = unicast_flush_resp(sk, hdr); - if (err || err2) - return err ? err : err2; + if (err || err2) { + if (err == -ESRCH) /* empty table - old silent behavior */ + return 0; + return err; + } c.data.type = XFRM_POLICY_TYPE_MAIN; c.event = XFRM_MSG_FLUSHPOLICY; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 4368e7b..d6eb16d 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -771,7 +771,8 @@ xfrm_policy_flush_secctx_check(struct net *net, u8 type, struct xfrm_audit *audi int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) { - int dir, err = 0; + int dir, err = 0, cnt = 0; + struct xfrm_policy *dp; write_lock_bh(&xfrm_policy_lock); @@ -789,8 +790,10 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) &net->xfrm.policy_inexact[dir], bydst) { if (pol->type != type) continue; - __xfrm_policy_unlink(pol, dir); + dp = __xfrm_policy_unlink(pol, dir); write_unlock_bh(&xfrm_policy_lock); + if (dp) + cnt++; xfrm_audit_policy_delete(pol, 1, audit_info->loginuid, audit_info->sessionid, @@ -809,8 +812,10 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) bydst) { if (pol->type != type) continue; - __xfrm_policy_unlink(pol, dir); + dp = __xfrm_policy_unlink(pol, dir); write_unlock_bh(&xfrm_policy_lock); + if (dp) + cnt++; xfrm_audit_policy_delete(pol, 1, audit_info->loginuid, @@ -824,6 +829,8 @@ int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) } } + if (!cnt) + err = -ESRCH; atomic_inc(&flow_cache_genid); out: write_unlock_bh(&xfrm_policy_lock); diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index cd94a9d..ee04e6b 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1679,8 +1679,12 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, audit_info.sessionid = NETLINK_CB(skb).sessionid; audit_info.secid = NETLINK_CB(skb).sid; err = xfrm_policy_flush(net, type, &audit_info); - if (err) + if (err) { + if (err == -ESRCH) /* empty table */ + return 0; return err; + } + c.data.type = type; c.event = nlh->nlmsg_type; c.seq = nlh->nlmsg_seq; -- 1.6.0.4 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 0/3] pfkey/xfrm SAD/SPD flushing fixes 2010-02-19 12:00 ` [PATCH 0/3] pfkey/xfrm SAD/SPD flushing fixes jamal 2010-02-19 12:00 ` [PATCH 1/3] pfkey: fix SA and SP flush sequence jamal @ 2010-02-19 21:12 ` David Miller 1 sibling, 0 replies; 5+ messages in thread From: David Miller @ 2010-02-19 21:12 UTC (permalink / raw) To: hadi; +Cc: adobriyan, netdev From: jamal <hadi@cyberus.ca> Date: Fri, 19 Feb 2010 07:00:39 -0500 > From: Jamal Hadi Salim <hadi@cyberus.ca> > > This patch set does split for pfkey response for flushing and > makes sure events for flush are generated only when we have > a non-empty SAD/SPD. We maintain current behavior of silence > when a table is empty. All applied, thanks Jamal. ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2010-02-19 21:12 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <flush-fix-xfrm>
2010-02-19 12:00 ` [PATCH 0/3] pfkey/xfrm SAD/SPD flushing fixes jamal
2010-02-19 12:00 ` [PATCH 1/3] pfkey: fix SA and SP flush sequence jamal
2010-02-19 12:00 ` [PATCH 2/3] xfrm: Flushing empty SAD generates false events jamal
2010-02-19 12:00 ` [PATCH 3/3] xfrm: Flushing empty SPD " jamal
2010-02-19 21:12 ` [PATCH 0/3] pfkey/xfrm SAD/SPD flushing fixes David Miller
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox