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

xfrm: security: iterate all, not inexact lists



currently all non-socket policies are either hashed in the dst table,
or placed on the 'inexact list'.  When flushing, we first walk the
table, then the (per-direction) inexact lists.

When we try and get rid of the inexact lists to having "n" inexact
lists (e.g. per-af inexact lists, or sorted into a tree), this walk
would become more complicated.

Simplify this: walk the 'all' list and skip socket policies during
traversal so we don't need to handle exact and inexact policies
separately anymore.

Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Acked-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarSteffen Klassert <steffen.klassert@secunet.com>
parent b69d540d
Loading
Loading
Loading
Loading
+26 −67
Original line number Original line Diff line number Diff line
@@ -892,38 +892,21 @@ EXPORT_SYMBOL(xfrm_policy_byid);
static inline int
static inline int
xfrm_policy_flush_secctx_check(struct net *net, u8 type, bool task_valid)
xfrm_policy_flush_secctx_check(struct net *net, u8 type, bool task_valid)
{
{
	int dir, err = 0;

	for (dir = 0; dir < XFRM_POLICY_MAX; dir++) {
	struct xfrm_policy *pol;
	struct xfrm_policy *pol;
		int i;
	int err = 0;


		hlist_for_each_entry(pol,
	list_for_each_entry(pol, &net->xfrm.policy_all, walk.all) {
				     &net->xfrm.policy_inexact[dir], bydst) {
		if (pol->walk.dead ||
			if (pol->type != type)
		    xfrm_policy_id2dir(pol->index) >= XFRM_POLICY_MAX ||
		    pol->type != type)
			continue;
			continue;

		err = security_xfrm_policy_delete(pol->security);
		err = security_xfrm_policy_delete(pol->security);
		if (err) {
		if (err) {
			xfrm_audit_policy_delete(pol, 0, task_valid);
			xfrm_audit_policy_delete(pol, 0, task_valid);
			return err;
			return err;
		}
		}
	}
	}
		for (i = net->xfrm.policy_bydst[dir].hmask; i >= 0; i--) {
			hlist_for_each_entry(pol,
					     net->xfrm.policy_bydst[dir].table + i,
					     bydst) {
				if (pol->type != type)
					continue;
				err = security_xfrm_policy_delete(
								pol->security);
				if (err) {
					xfrm_audit_policy_delete(pol, 0,
								 task_valid);
					return err;
				}
			}
		}
	}
	return err;
	return err;
}
}
#else
#else
@@ -937,6 +920,7 @@ xfrm_policy_flush_secctx_check(struct net *net, u8 type, bool task_valid)
int xfrm_policy_flush(struct net *net, u8 type, bool task_valid)
int xfrm_policy_flush(struct net *net, u8 type, bool task_valid)
{
{
	int dir, err = 0, cnt = 0;
	int dir, err = 0, cnt = 0;
	struct xfrm_policy *pol;


	spin_lock_bh(&net->xfrm.xfrm_policy_lock);
	spin_lock_bh(&net->xfrm.xfrm_policy_lock);


@@ -944,46 +928,21 @@ int xfrm_policy_flush(struct net *net, u8 type, bool task_valid)
	if (err)
	if (err)
		goto out;
		goto out;


	for (dir = 0; dir < XFRM_POLICY_MAX; dir++) {
again:
		struct xfrm_policy *pol;
	list_for_each_entry(pol, &net->xfrm.policy_all, walk.all) {
		int i;
		dir = xfrm_policy_id2dir(pol->index);

		if (pol->walk.dead ||
	again1:
		    dir >= XFRM_POLICY_MAX ||
		hlist_for_each_entry(pol,
		    pol->type != type)
				     &net->xfrm.policy_inexact[dir], bydst) {
			if (pol->type != type)
			continue;
			continue;
			__xfrm_policy_unlink(pol, dir);
			spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
			cnt++;


			xfrm_audit_policy_delete(pol, 1, task_valid);

			xfrm_policy_kill(pol);

			spin_lock_bh(&net->xfrm.xfrm_policy_lock);
			goto again1;
		}

		for (i = net->xfrm.policy_bydst[dir].hmask; i >= 0; i--) {
	again2:
			hlist_for_each_entry(pol,
					     net->xfrm.policy_bydst[dir].table + i,
					     bydst) {
				if (pol->type != type)
					continue;
		__xfrm_policy_unlink(pol, dir);
		__xfrm_policy_unlink(pol, dir);
		spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
		spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
		cnt++;
		cnt++;

		xfrm_audit_policy_delete(pol, 1, task_valid);
		xfrm_audit_policy_delete(pol, 1, task_valid);
		xfrm_policy_kill(pol);
		xfrm_policy_kill(pol);

		spin_lock_bh(&net->xfrm.xfrm_policy_lock);
		spin_lock_bh(&net->xfrm.xfrm_policy_lock);
				goto again2;
		goto again;
			}
		}

	}
	}
	if (!cnt)
	if (!cnt)
		err = -ESRCH;
		err = -ESRCH;