Commit 88584c30 authored by Florian Westphal's avatar Florian Westphal Committed by Steffen Klassert
Browse files

xfrm: policy: fix policy hash rebuild



Dan Carpenter reports following static checker warning:
 net/xfrm/xfrm_policy.c:1316 xfrm_hash_rebuild()
 warn: 'dir' is out of bounds '3' vs '2'

 |  1280          /* reset the bydst and inexact table in all directions */
 |  1281          xfrm_hash_reset_inexact_table(net);
 |  1282
 |  1283          for (dir = 0; dir < XFRM_POLICY_MAX; dir++) {
 |                              ^^^^^^^^^^^^^^^^^^^^^
 |dir == XFRM_POLICY_MAX at the end of this loop.
 |  1304          /* re-insert all policies by order of creation */
 |  1305          list_for_each_entry_reverse(policy, &net->xfrm.policy_all, walk.all) {
 [..]
 |  1314                                            xfrm_policy_id2dir(policy->index));
 |  1315                  if (!chain) {
 |  1316                          void *p = xfrm_policy_inexact_insert(policy, dir, 0);

Fix this by updating 'dir' based on current policy.  Otherwise, the
inexact policies won't be found anymore during lookup, as they get
hashed to a bogus bin.

Reported-by: default avatarDan Carpenter <dan.carpenter@oracle.com>
Fixes: cc1bb845 ("xfrm: policy: return NULL when inexact search needed")
Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarSteffen Klassert <steffen.klassert@secunet.com>
parent 3fcccec0
Loading
Loading
Loading
Loading
+5 −4
Original line number Original line Diff line number Diff line
@@ -1303,15 +1303,16 @@ static void xfrm_hash_rebuild(struct work_struct *work)


	/* re-insert all policies by order of creation */
	/* re-insert all policies by order of creation */
	list_for_each_entry_reverse(policy, &net->xfrm.policy_all, walk.all) {
	list_for_each_entry_reverse(policy, &net->xfrm.policy_all, walk.all) {
		if (policy->walk.dead ||
		if (policy->walk.dead)
		    xfrm_policy_id2dir(policy->index) >= XFRM_POLICY_MAX) {
			continue;
		dir = xfrm_policy_id2dir(policy->index);
		if (dir >= XFRM_POLICY_MAX) {
			/* skip socket policies */
			/* skip socket policies */
			continue;
			continue;
		}
		}
		newpos = NULL;
		newpos = NULL;
		chain = policy_hash_bysel(net, &policy->selector,
		chain = policy_hash_bysel(net, &policy->selector,
					  policy->family,
					  policy->family, dir);
					  xfrm_policy_id2dir(policy->index));
		if (!chain) {
		if (!chain) {
			void *p = xfrm_policy_inexact_insert(policy, dir, 0);
			void *p = xfrm_policy_inexact_insert(policy, dir, 0);