diff options
Diffstat (limited to 'net/xfrm/xfrm_policy.c')
| -rw-r--r-- | net/xfrm/xfrm_policy.c | 28 | 
1 files changed, 18 insertions, 10 deletions
| diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 04d1ce9b510f..00bd0ecff5a1 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -2593,12 +2593,14 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,  		if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {  			__u32 mark = 0; +			int oif;  			if (xfrm[i]->props.smark.v || xfrm[i]->props.smark.m)  				mark = xfrm_smark_get(fl->flowi_mark, xfrm[i]);  			family = xfrm[i]->props.family; -			dst = xfrm_dst_lookup(xfrm[i], tos, fl->flowi_oif, +			oif = fl->flowi_oif ? : fl->flowi_l3mdev; +			dst = xfrm_dst_lookup(xfrm[i], tos, oif,  					      &saddr, &daddr, family, mark);  			err = PTR_ERR(dst);  			if (IS_ERR(dst)) @@ -3158,7 +3160,7 @@ ok:  nopol:  	if (!(dst_orig->dev->flags & IFF_LOOPBACK) && -	    !xfrm_default_allow(net, dir)) { +	    net->xfrm.policy_default[dir] == XFRM_USERPOLICY_BLOCK) {  		err = -EPERM;  		goto error;  	} @@ -3569,7 +3571,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,  	}  	if (!pol) { -		if (!xfrm_default_allow(net, dir)) { +		if (net->xfrm.policy_default[dir] == XFRM_USERPOLICY_BLOCK) {  			XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOPOLS);  			return 0;  		} @@ -3629,7 +3631,8 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,  		}  		xfrm_nr = ti; -		if (!xfrm_default_allow(net, dir) && !xfrm_nr) { +		if (net->xfrm.policy_default[dir] == XFRM_USERPOLICY_BLOCK && +		    !xfrm_nr) {  			XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOSTATES);  			goto reject;  		} @@ -4118,6 +4121,9 @@ static int __net_init xfrm_net_init(struct net *net)  	spin_lock_init(&net->xfrm.xfrm_policy_lock);  	seqcount_spinlock_init(&net->xfrm.xfrm_policy_hash_generation, &net->xfrm.xfrm_policy_lock);  	mutex_init(&net->xfrm.xfrm_cfg_mutex); +	net->xfrm.policy_default[XFRM_POLICY_IN] = XFRM_USERPOLICY_ACCEPT; +	net->xfrm.policy_default[XFRM_POLICY_FWD] = XFRM_USERPOLICY_ACCEPT; +	net->xfrm.policy_default[XFRM_POLICY_OUT] = XFRM_USERPOLICY_ACCEPT;  	rv = xfrm_statistics_init(net);  	if (rv < 0) @@ -4256,7 +4262,7 @@ static bool xfrm_migrate_selector_match(const struct xfrm_selector *sel_cmp,  }  static struct xfrm_policy *xfrm_migrate_policy_find(const struct xfrm_selector *sel, -						    u8 dir, u8 type, struct net *net) +						    u8 dir, u8 type, struct net *net, u32 if_id)  {  	struct xfrm_policy *pol, *ret = NULL;  	struct hlist_head *chain; @@ -4265,7 +4271,8 @@ static struct xfrm_policy *xfrm_migrate_policy_find(const struct xfrm_selector *  	spin_lock_bh(&net->xfrm.xfrm_policy_lock);  	chain = policy_hash_direct(net, &sel->daddr, &sel->saddr, sel->family, dir);  	hlist_for_each_entry(pol, chain, bydst) { -		if (xfrm_migrate_selector_match(sel, &pol->selector) && +		if ((if_id == 0 || pol->if_id == if_id) && +		    xfrm_migrate_selector_match(sel, &pol->selector) &&  		    pol->type == type) {  			ret = pol;  			priority = ret->priority; @@ -4277,7 +4284,8 @@ static struct xfrm_policy *xfrm_migrate_policy_find(const struct xfrm_selector *  		if ((pol->priority >= priority) && ret)  			break; -		if (xfrm_migrate_selector_match(sel, &pol->selector) && +		if ((if_id == 0 || pol->if_id == if_id) && +		    xfrm_migrate_selector_match(sel, &pol->selector) &&  		    pol->type == type) {  			ret = pol;  			break; @@ -4393,7 +4401,7 @@ static int xfrm_migrate_check(const struct xfrm_migrate *m, int num_migrate)  int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,  		 struct xfrm_migrate *m, int num_migrate,  		 struct xfrm_kmaddress *k, struct net *net, -		 struct xfrm_encap_tmpl *encap) +		 struct xfrm_encap_tmpl *encap, u32 if_id)  {  	int i, err, nx_cur = 0, nx_new = 0;  	struct xfrm_policy *pol = NULL; @@ -4412,14 +4420,14 @@ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,  	}  	/* Stage 1 - find policy */ -	if ((pol = xfrm_migrate_policy_find(sel, dir, type, net)) == NULL) { +	if ((pol = xfrm_migrate_policy_find(sel, dir, type, net, if_id)) == NULL) {  		err = -ENOENT;  		goto out;  	}  	/* Stage 2 - find and update state(s) */  	for (i = 0, mp = m; i < num_migrate; i++, mp++) { -		if ((x = xfrm_migrate_state_find(mp, net))) { +		if ((x = xfrm_migrate_state_find(mp, net, if_id))) {  			x_cur[nx_cur] = x;  			nx_cur++;  			xc = xfrm_state_migrate(x, mp, encap); | 
