summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2016-07-29 09:57:32 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-07-03 11:21:32 +0200
commit3a727fcad231965fe1554287d4ff2e769b5270bf (patch)
treec1709d5365173d8f11102cc361a25b16aaf38244 /net
parent9c3a27c0ca1ef54b99a24c154dc3b068b3c9ddc3 (diff)
xfrm: Ignore socket policies when rebuilding hash tables
commit 6916fb3b10b3cbe3b1f9f5b680675f53e4e299eb upstream. Whenever thresholds are changed the hash tables are rebuilt. This is done by enumerating all policies and hashing and inserting them into the right table according to the thresholds and direction. Because socket policies are also contained in net->xfrm.policy_all but no hash tables are defined for their direction (dir + XFRM_POLICY_MAX) this causes a NULL or invalid pointer dereference after returning from policy_hash_bysel() if the rebuild is done while any socket policies are installed. Since the rebuild after changing thresholds is scheduled this crash could even occur if the userland sets thresholds seemingly before installing any socket policies. Fixes: 53c2e285f970 ("xfrm: Do not hash socket policies") Signed-off-by: Tobias Brunner <tobias@strongswan.org> Acked-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com> Cc: Zubin Mithra <zsm@chromium.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net')
-rw-r--r--net/xfrm/xfrm_policy.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index d95cb69460f0..3c16aee93dfe 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -626,6 +626,10 @@ static void xfrm_hash_rebuild(struct work_struct *work)
/* re-insert all policies by order of creation */
list_for_each_entry_reverse(policy, &net->xfrm.policy_all, walk.all) {
+ if (xfrm_policy_id2dir(policy->index) >= XFRM_POLICY_MAX) {
+ /* skip socket policies */
+ continue;
+ }
newpos = NULL;
chain = policy_hash_bysel(net, &policy->selector,
policy->family,