Skip to content

Commit

Permalink
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/gi…
Browse files Browse the repository at this point in the history
…t/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: David S. Miller <davem@davemloft.net>
  • Loading branch information
davem330 committed Sep 28, 2020
2 parents 709a16b + e94ee17 commit a4be47a
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 17 deletions.
16 changes: 6 additions & 10 deletions include/net/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
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);
if (!x->replay_esn)
return -ENOMEM;

x->replay_esn->bmp_len = orig->replay_esn->bmp_len;
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),
x->preplay_esn = kmemdup(orig->preplay_esn,
xfrm_replay_state_esn_len(orig->preplay_esn),
GFP_KERNEL);
if (!x->preplay_esn) {
kfree(x->replay_esn);
if (!x->preplay_esn)
return -ENOMEM;
}

return 0;
}
Expand Down
2 changes: 2 additions & 0 deletions net/ipv4/ip_vti.c
Original file line number Diff line number Diff line change
Expand Up @@ -490,13 +490,15 @@ static struct xfrm_tunnel vti_ipip_handler __read_mostly = {
.priority = 0,
};

#if IS_ENABLED(CONFIG_IPV6)
static struct xfrm_tunnel vti_ipip6_handler __read_mostly = {
.handler = vti_rcv_tunnel,
.cb_handler = vti_rcv_cb,
.err_handler = vti4_err,
.priority = 0,
};
#endif
#endif

static int __net_init vti_init_net(struct net *net)
{
Expand Down
6 changes: 5 additions & 1 deletion net/xfrm/espintcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
struct tcp_skb_cb *tcp_cb = (struct tcp_skb_cb *)skb->cb;

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();
skb->dev = dev_get_by_index_rcu(sock_net(sk), skb->skb_iif);
Expand Down
2 changes: 1 addition & 1 deletion net/xfrm/xfrm_interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
}

mtu = dst_mtu(dst);
if (!skb->ignore_df && skb->len > mtu) {
if (skb->len > mtu) {
skb_dst_update_pmtu_no_confirm(skb, mtu);

if (skb->protocol == htons(ETH_P_IPV6)) {
Expand Down
42 changes: 37 additions & 5 deletions net/xfrm/xfrm_state.c
Original file line number Diff line number Diff line change
Expand Up @@ -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->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))
return;

Expand All @@ -1032,7 +1033,9 @@ static void xfrm_state_look_at(struct xfrm_policy *pol, struct xfrm_state *x,
*acq_in_progress = 1;
} else if (x->km.state == XFRM_STATE_ERROR ||
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))
*error = -ESRCH;
}
Expand Down Expand Up @@ -1072,7 +1075,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
tmpl->mode == x->props.mode &&
tmpl->id.proto == x->id.proto &&
(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);
}
if (best || acquire_in_progress)
Expand All @@ -1089,7 +1092,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
tmpl->mode == x->props.mode &&
tmpl->id.proto == x->id.proto &&
(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);
}

Expand Down Expand Up @@ -1441,6 +1444,30 @@ int xfrm_state_add(struct xfrm_state *x)
EXPORT_SYMBOL(xfrm_state_add);

#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,
struct xfrm_encap_tmpl *encap)
{
Expand Down Expand Up @@ -1497,6 +1524,10 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
goto error;
}

if (orig->security)
if (clone_security(x, orig->security))
goto error;

if (orig->coaddr) {
x->coaddr = kmemdup(orig->coaddr, sizeof(*x->coaddr),
GFP_KERNEL);
Expand All @@ -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->props.smark, &orig->props.smark, sizeof(x->props.smark));

if (xfrm_init_state(x) < 0)
goto error;
Expand All @@ -1521,7 +1553,7 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
x->tfcpad = orig->tfcpad;
x->replay_maxdiff = orig->replay_maxdiff;
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.seq = orig->km.seq;
x->replay = orig->replay;
Expand Down

0 comments on commit a4be47a

Please sign in to comment.