diff options
Diffstat (limited to 'net/xfrm/xfrm_state.c')
| -rw-r--r-- | net/xfrm/xfrm_state.c | 11 | 
1 files changed, 9 insertions, 2 deletions
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 500b3391f474..429957412633 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -313,13 +313,14 @@ retry:  	if ((type && !try_module_get(type->owner)))  		type = NULL; +	rcu_read_unlock(); +  	if (!type && try_load) {  		request_module("xfrm-offload-%d-%d", family, proto);  		try_load = 0;  		goto retry;  	} -	rcu_read_unlock();  	return type;  } @@ -1534,8 +1535,12 @@ out:  	err = -EINVAL;  	spin_lock_bh(&x1->lock);  	if (likely(x1->km.state == XFRM_STATE_VALID)) { -		if (x->encap && x1->encap) +		if (x->encap && x1->encap && +		    x->encap->encap_type == x1->encap->encap_type)  			memcpy(x1->encap, x->encap, sizeof(*x1->encap)); +		else if (x->encap || x1->encap) +			goto fail; +  		if (x->coaddr && x1->coaddr) {  			memcpy(x1->coaddr, x->coaddr, sizeof(*x1->coaddr));  		} @@ -1552,6 +1557,8 @@ out:  		x->km.state = XFRM_STATE_DEAD;  		__xfrm_state_put(x);  	} + +fail:  	spin_unlock_bh(&x1->lock);  	xfrm_state_put(x1);  | 
