diff options
Diffstat (limited to 'net/xfrm/xfrm_user.c')
| -rw-r--r-- | net/xfrm/xfrm_user.c | 47 | 
1 files changed, 43 insertions, 4 deletions
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index cf5172d4ce68..d720e163ae6e 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -901,6 +901,8 @@ static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p)  	memcpy(&p->id, &x->id, sizeof(p->id));  	memcpy(&p->sel, &x->sel, sizeof(p->sel));  	memcpy(&p->lft, &x->lft, sizeof(p->lft)); +	if (x->xso.dev) +		xfrm_dev_state_update_curlft(x);  	memcpy(&p->curlft, &x->curlft, sizeof(p->curlft));  	put_unaligned(x->stats.replay_window, &p->stats.replay_window);  	put_unaligned(x->stats.replay, &p->stats.replay); @@ -1012,7 +1014,9 @@ static int copy_to_user_aead(struct xfrm_algo_aead *aead, struct sk_buff *skb)  		return -EMSGSIZE;  	ap = nla_data(nla); -	memcpy(ap, aead, sizeof(*aead)); +	strscpy_pad(ap->alg_name, aead->alg_name, sizeof(ap->alg_name)); +	ap->alg_key_len = aead->alg_key_len; +	ap->alg_icv_len = aead->alg_icv_len;  	if (redact_secret && aead->alg_key_len)  		memset(ap->alg_key, 0, (aead->alg_key_len + 7) / 8); @@ -1032,7 +1036,8 @@ static int copy_to_user_ealg(struct xfrm_algo *ealg, struct sk_buff *skb)  		return -EMSGSIZE;  	ap = nla_data(nla); -	memcpy(ap, ealg, sizeof(*ealg)); +	strscpy_pad(ap->alg_name, ealg->alg_name, sizeof(ap->alg_name)); +	ap->alg_key_len = ealg->alg_key_len;  	if (redact_secret && ealg->alg_key_len)  		memset(ap->alg_key, 0, (ealg->alg_key_len + 7) / 8); @@ -1043,6 +1048,40 @@ static int copy_to_user_ealg(struct xfrm_algo *ealg, struct sk_buff *skb)  	return 0;  } +static int copy_to_user_calg(struct xfrm_algo *calg, struct sk_buff *skb) +{ +	struct nlattr *nla = nla_reserve(skb, XFRMA_ALG_COMP, sizeof(*calg)); +	struct xfrm_algo *ap; + +	if (!nla) +		return -EMSGSIZE; + +	ap = nla_data(nla); +	strscpy_pad(ap->alg_name, calg->alg_name, sizeof(ap->alg_name)); +	ap->alg_key_len = 0; + +	return 0; +} + +static int copy_to_user_encap(struct xfrm_encap_tmpl *ep, struct sk_buff *skb) +{ +	struct nlattr *nla = nla_reserve(skb, XFRMA_ENCAP, sizeof(*ep)); +	struct xfrm_encap_tmpl *uep; + +	if (!nla) +		return -EMSGSIZE; + +	uep = nla_data(nla); +	memset(uep, 0, sizeof(*uep)); + +	uep->encap_type = ep->encap_type; +	uep->encap_sport = ep->encap_sport; +	uep->encap_dport = ep->encap_dport; +	uep->encap_oa = ep->encap_oa; + +	return 0; +} +  static int xfrm_smark_put(struct sk_buff *skb, struct xfrm_mark *m)  {  	int ret = 0; @@ -1098,12 +1137,12 @@ static int copy_to_user_state_extra(struct xfrm_state *x,  			goto out;  	}  	if (x->calg) { -		ret = nla_put(skb, XFRMA_ALG_COMP, sizeof(*(x->calg)), x->calg); +		ret = copy_to_user_calg(x->calg, skb);  		if (ret)  			goto out;  	}  	if (x->encap) { -		ret = nla_put(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap); +		ret = copy_to_user_encap(x->encap, skb);  		if (ret)  			goto out;  	}  |