Commit a4be47af authored by David S. Miller's avatar David S. Miller

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec

Steffen Klassert says:

====================
pull request (net): ipsec 2020-09-28

1) Fix a build warning in ip_vti if CONFIG_IPV6 is not set.
   From YueHaibing.

2) Restore IPCB on espintcp before handing the packet to xfrm
   as the information there is still needed.
   From Sabrina Dubroca.

3) Fix pmtu updating for xfrm interfaces.
   From Sabrina Dubroca.

4) Some xfrm state information was not cloned with xfrm_do_migrate.
   Fixes to clone the full xfrm state, from Antony Antony.

5) Use the correct address family in xfrm_state_find. The struct
   flowi must always be interpreted along with the original
   address family. This got lost over the years.
   Fix from Herbert Xu.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 709a16be e94ee171
...@@ -1773,21 +1773,17 @@ static inline unsigned int xfrm_replay_state_esn_len(struct xfrm_replay_state_es ...@@ -1773,21 +1773,17 @@ static inline unsigned int xfrm_replay_state_esn_len(struct xfrm_replay_state_es
static inline int xfrm_replay_clone(struct xfrm_state *x, static inline int xfrm_replay_clone(struct xfrm_state *x,
struct xfrm_state *orig) struct xfrm_state *orig)
{ {
x->replay_esn = kzalloc(xfrm_replay_state_esn_len(orig->replay_esn),
x->replay_esn = kmemdup(orig->replay_esn,
xfrm_replay_state_esn_len(orig->replay_esn),
GFP_KERNEL); GFP_KERNEL);
if (!x->replay_esn) if (!x->replay_esn)
return -ENOMEM; return -ENOMEM;
x->preplay_esn = kmemdup(orig->preplay_esn,
x->replay_esn->bmp_len = orig->replay_esn->bmp_len; xfrm_replay_state_esn_len(orig->preplay_esn),
x->replay_esn->replay_window = orig->replay_esn->replay_window;
x->preplay_esn = kmemdup(x->replay_esn,
xfrm_replay_state_esn_len(x->replay_esn),
GFP_KERNEL); GFP_KERNEL);
if (!x->preplay_esn) { if (!x->preplay_esn)
kfree(x->replay_esn);
return -ENOMEM; return -ENOMEM;
}
return 0; return 0;
} }
......
...@@ -490,6 +490,7 @@ static struct xfrm_tunnel vti_ipip_handler __read_mostly = { ...@@ -490,6 +490,7 @@ static struct xfrm_tunnel vti_ipip_handler __read_mostly = {
.priority = 0, .priority = 0,
}; };
#if IS_ENABLED(CONFIG_IPV6)
static struct xfrm_tunnel vti_ipip6_handler __read_mostly = { static struct xfrm_tunnel vti_ipip6_handler __read_mostly = {
.handler = vti_rcv_tunnel, .handler = vti_rcv_tunnel,
.cb_handler = vti_rcv_cb, .cb_handler = vti_rcv_cb,
...@@ -497,6 +498,7 @@ static struct xfrm_tunnel vti_ipip6_handler __read_mostly = { ...@@ -497,6 +498,7 @@ static struct xfrm_tunnel vti_ipip6_handler __read_mostly = {
.priority = 0, .priority = 0,
}; };
#endif #endif
#endif
static int __net_init vti_init_net(struct net *net) static int __net_init vti_init_net(struct net *net)
{ {
......
...@@ -29,8 +29,12 @@ static void handle_nonesp(struct espintcp_ctx *ctx, struct sk_buff *skb, ...@@ -29,8 +29,12 @@ static void handle_nonesp(struct espintcp_ctx *ctx, struct sk_buff *skb,
static void handle_esp(struct sk_buff *skb, struct sock *sk) static void handle_esp(struct sk_buff *skb, struct sock *sk)
{ {
struct tcp_skb_cb *tcp_cb = (struct tcp_skb_cb *)skb->cb;
skb_reset_transport_header(skb); skb_reset_transport_header(skb);
memset(skb->cb, 0, sizeof(skb->cb));
/* restore IP CB, we need at least IP6CB->nhoff */
memmove(skb->cb, &tcp_cb->header, sizeof(tcp_cb->header));
rcu_read_lock(); rcu_read_lock();
skb->dev = dev_get_by_index_rcu(sock_net(sk), skb->skb_iif); skb->dev = dev_get_by_index_rcu(sock_net(sk), skb->skb_iif);
......
...@@ -303,7 +303,7 @@ xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) ...@@ -303,7 +303,7 @@ xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
} }
mtu = dst_mtu(dst); mtu = dst_mtu(dst);
if (!skb->ignore_df && skb->len > mtu) { if (skb->len > mtu) {
skb_dst_update_pmtu_no_confirm(skb, mtu); skb_dst_update_pmtu_no_confirm(skb, mtu);
if (skb->protocol == htons(ETH_P_IPV6)) { if (skb->protocol == htons(ETH_P_IPV6)) {
......
...@@ -1019,7 +1019,8 @@ static void xfrm_state_look_at(struct xfrm_policy *pol, struct xfrm_state *x, ...@@ -1019,7 +1019,8 @@ static void xfrm_state_look_at(struct xfrm_policy *pol, struct xfrm_state *x,
*/ */
if (x->km.state == XFRM_STATE_VALID) { if (x->km.state == XFRM_STATE_VALID) {
if ((x->sel.family && if ((x->sel.family &&
!xfrm_selector_match(&x->sel, fl, x->sel.family)) || (x->sel.family != family ||
!xfrm_selector_match(&x->sel, fl, family))) ||
!security_xfrm_state_pol_flow_match(x, pol, fl)) !security_xfrm_state_pol_flow_match(x, pol, fl))
return; return;
...@@ -1032,7 +1033,9 @@ static void xfrm_state_look_at(struct xfrm_policy *pol, struct xfrm_state *x, ...@@ -1032,7 +1033,9 @@ static void xfrm_state_look_at(struct xfrm_policy *pol, struct xfrm_state *x,
*acq_in_progress = 1; *acq_in_progress = 1;
} else if (x->km.state == XFRM_STATE_ERROR || } else if (x->km.state == XFRM_STATE_ERROR ||
x->km.state == XFRM_STATE_EXPIRED) { x->km.state == XFRM_STATE_EXPIRED) {
if (xfrm_selector_match(&x->sel, fl, x->sel.family) && if ((!x->sel.family ||
(x->sel.family == family &&
xfrm_selector_match(&x->sel, fl, family))) &&
security_xfrm_state_pol_flow_match(x, pol, fl)) security_xfrm_state_pol_flow_match(x, pol, fl))
*error = -ESRCH; *error = -ESRCH;
} }
...@@ -1072,7 +1075,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr, ...@@ -1072,7 +1075,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
tmpl->mode == x->props.mode && tmpl->mode == x->props.mode &&
tmpl->id.proto == x->id.proto && tmpl->id.proto == x->id.proto &&
(tmpl->id.spi == x->id.spi || !tmpl->id.spi)) (tmpl->id.spi == x->id.spi || !tmpl->id.spi))
xfrm_state_look_at(pol, x, fl, encap_family, xfrm_state_look_at(pol, x, fl, family,
&best, &acquire_in_progress, &error); &best, &acquire_in_progress, &error);
} }
if (best || acquire_in_progress) if (best || acquire_in_progress)
...@@ -1089,7 +1092,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr, ...@@ -1089,7 +1092,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
tmpl->mode == x->props.mode && tmpl->mode == x->props.mode &&
tmpl->id.proto == x->id.proto && tmpl->id.proto == x->id.proto &&
(tmpl->id.spi == x->id.spi || !tmpl->id.spi)) (tmpl->id.spi == x->id.spi || !tmpl->id.spi))
xfrm_state_look_at(pol, x, fl, encap_family, xfrm_state_look_at(pol, x, fl, family,
&best, &acquire_in_progress, &error); &best, &acquire_in_progress, &error);
} }
...@@ -1441,6 +1444,30 @@ int xfrm_state_add(struct xfrm_state *x) ...@@ -1441,6 +1444,30 @@ int xfrm_state_add(struct xfrm_state *x)
EXPORT_SYMBOL(xfrm_state_add); EXPORT_SYMBOL(xfrm_state_add);
#ifdef CONFIG_XFRM_MIGRATE #ifdef CONFIG_XFRM_MIGRATE
static inline int clone_security(struct xfrm_state *x, struct xfrm_sec_ctx *security)
{
struct xfrm_user_sec_ctx *uctx;
int size = sizeof(*uctx) + security->ctx_len;
int err;
uctx = kmalloc(size, GFP_KERNEL);
if (!uctx)
return -ENOMEM;
uctx->exttype = XFRMA_SEC_CTX;
uctx->len = size;
uctx->ctx_doi = security->ctx_doi;
uctx->ctx_alg = security->ctx_alg;
uctx->ctx_len = security->ctx_len;
memcpy(uctx + 1, security->ctx_str, security->ctx_len);
err = security_xfrm_state_alloc(x, uctx);
kfree(uctx);
if (err)
return err;
return 0;
}
static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
struct xfrm_encap_tmpl *encap) struct xfrm_encap_tmpl *encap)
{ {
...@@ -1497,6 +1524,10 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, ...@@ -1497,6 +1524,10 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
goto error; goto error;
} }
if (orig->security)
if (clone_security(x, orig->security))
goto error;
if (orig->coaddr) { if (orig->coaddr) {
x->coaddr = kmemdup(orig->coaddr, sizeof(*x->coaddr), x->coaddr = kmemdup(orig->coaddr, sizeof(*x->coaddr),
GFP_KERNEL); GFP_KERNEL);
...@@ -1510,6 +1541,7 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, ...@@ -1510,6 +1541,7 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
} }
memcpy(&x->mark, &orig->mark, sizeof(x->mark)); memcpy(&x->mark, &orig->mark, sizeof(x->mark));
memcpy(&x->props.smark, &orig->props.smark, sizeof(x->props.smark));
if (xfrm_init_state(x) < 0) if (xfrm_init_state(x) < 0)
goto error; goto error;
...@@ -1521,7 +1553,7 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, ...@@ -1521,7 +1553,7 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
x->tfcpad = orig->tfcpad; x->tfcpad = orig->tfcpad;
x->replay_maxdiff = orig->replay_maxdiff; x->replay_maxdiff = orig->replay_maxdiff;
x->replay_maxage = orig->replay_maxage; x->replay_maxage = orig->replay_maxage;
x->curlft.add_time = orig->curlft.add_time; memcpy(&x->curlft, &orig->curlft, sizeof(x->curlft));
x->km.state = orig->km.state; x->km.state = orig->km.state;
x->km.seq = orig->km.seq; x->km.seq = orig->km.seq;
x->replay = orig->replay; x->replay = orig->replay;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment