xfrm: force a garbage collection after deleting a policy
authorPaul Moore <pmoore@redhat.com>
Wed, 29 May 2013 07:36:25 +0000 (07:36 +0000)
committerDavid S. Miller <davem@davemloft.net>
Sat, 1 Jun 2013 00:30:07 +0000 (17:30 -0700)
In some cases after deleting a policy from the SPD the policy would
remain in the dst/flow/route cache for an extended period of time
which caused problems for SELinux as its dynamic network access
controls key off of the number of XFRM policy and state entries.
This patch corrects this problem by forcing a XFRM garbage collection
whenever a policy is sucessfully removed.

Reported-by: Ondrej Moris <omoris@redhat.com>
Signed-off-by: Paul Moore <pmoore@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/xfrm.h
net/key/af_key.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_user.c

index ae16531d0d353741ac66c83e0464341d060d5cce..94ce082b29dcdba2d726cbc90a0c4510fd38fb2b 100644 (file)
@@ -1160,6 +1160,8 @@ static inline void xfrm_sk_free_policy(struct sock *sk)
        }
 }
 
+extern void xfrm_garbage_collect(struct net *net);
+
 #else
 
 static inline void xfrm_sk_free_policy(struct sock *sk) {}
@@ -1194,6 +1196,9 @@ static inline int xfrm6_policy_check_reverse(struct sock *sk, int dir,
 {
        return 1;
 }
+static inline void xfrm_garbage_collect(struct net *net)
+{
+}
 #endif
 
 static __inline__
index 5b1e5af257137e4c6a03a2c575f1adb5a949e25e..c5fbd7589681cf984220325fff463696163340d0 100644 (file)
@@ -2366,6 +2366,8 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, const struct sa
 
 out:
        xfrm_pol_put(xp);
+       if (err == 0)
+               xfrm_garbage_collect(net);
        return err;
 }
 
@@ -2615,6 +2617,8 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, const struct sadb_
 
 out:
        xfrm_pol_put(xp);
+       if (delete && err == 0)
+               xfrm_garbage_collect(net);
        return err;
 }
 
index 23cea0f74336c72b332e909994e242d216e5e2ae..ea970b8002a20a614a5bc9fe89afa3c39b131180 100644 (file)
@@ -2557,11 +2557,12 @@ static void __xfrm_garbage_collect(struct net *net)
        }
 }
 
-static void xfrm_garbage_collect(struct net *net)
+void xfrm_garbage_collect(struct net *net)
 {
        flow_cache_flush();
        __xfrm_garbage_collect(net);
 }
+EXPORT_SYMBOL(xfrm_garbage_collect);
 
 static void xfrm_garbage_collect_deferred(struct net *net)
 {
index aa778748c56592728866ce24096bf46447c2d13c..3f565e495ac68cea83e1d52cf7db7e820fe777ad 100644 (file)
@@ -1681,6 +1681,8 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
 
 out:
        xfrm_pol_put(xp);
+       if (delete && err == 0)
+               xfrm_garbage_collect(net);
        return err;
 }