Commit 020295d9 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 2018-03-29

1) Fix a rcu_read_lock/rcu_read_unlock imbalance
   in the error path of xfrm_local_error().
   From Taehee Yoo.

2) Some VTI MTU fixes. From Stefano Brivio.

3) Fix a too early overwritten skb control buffer
   on xfrm transport mode.

Please note that this pull request has a merge conflict
in net/ipv4/ip_tunnel.c.

The conflict is between

commit f6cc9c05 ("ip_tunnel: Emit events for post-register MTU changes")

from the net tree and

commit 24fc7979 ("ip_tunnel: Clamp MTU to bounds on new link")

from the ipsec tree.

It can be solved as it is currently done in linux-next.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents b9fc828d 9a3fb9fb
...@@ -1117,7 +1117,12 @@ int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[], ...@@ -1117,7 +1117,12 @@ int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[],
eth_hw_addr_random(dev); eth_hw_addr_random(dev);
mtu = ip_tunnel_bind_dev(dev); mtu = ip_tunnel_bind_dev(dev);
if (!tb[IFLA_MTU]) { if (tb[IFLA_MTU]) {
unsigned int max = 0xfff8 - dev->hard_header_len - nt->hlen;
dev->mtu = clamp(dev->mtu, (unsigned int)ETH_MIN_MTU,
(unsigned int)(max - sizeof(struct iphdr)));
} else {
err = dev_set_mtu(dev, mtu); err = dev_set_mtu(dev, mtu);
if (err) if (err)
goto err_dev_set_mtu; goto err_dev_set_mtu;
......
...@@ -387,8 +387,6 @@ static int vti_tunnel_init(struct net_device *dev) ...@@ -387,8 +387,6 @@ static int vti_tunnel_init(struct net_device *dev)
memcpy(dev->dev_addr, &iph->saddr, 4); memcpy(dev->dev_addr, &iph->saddr, 4);
memcpy(dev->broadcast, &iph->daddr, 4); memcpy(dev->broadcast, &iph->daddr, 4);
dev->hard_header_len = LL_MAX_HEADER + sizeof(struct iphdr);
dev->mtu = ETH_DATA_LEN;
dev->flags = IFF_NOARP; dev->flags = IFF_NOARP;
dev->addr_len = 4; dev->addr_len = 4;
dev->features |= NETIF_F_LLTX; dev->features |= NETIF_F_LLTX;
......
...@@ -622,11 +622,12 @@ static int vti6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, ...@@ -622,11 +622,12 @@ static int vti6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
return 0; return 0;
} }
static void vti6_link_config(struct ip6_tnl *t) static void vti6_link_config(struct ip6_tnl *t, bool keep_mtu)
{ {
struct net_device *dev = t->dev; struct net_device *dev = t->dev;
struct __ip6_tnl_parm *p = &t->parms; struct __ip6_tnl_parm *p = &t->parms;
struct net_device *tdev = NULL; struct net_device *tdev = NULL;
int mtu;
memcpy(dev->dev_addr, &p->laddr, sizeof(struct in6_addr)); memcpy(dev->dev_addr, &p->laddr, sizeof(struct in6_addr));
memcpy(dev->broadcast, &p->raddr, sizeof(struct in6_addr)); memcpy(dev->broadcast, &p->raddr, sizeof(struct in6_addr));
...@@ -640,6 +641,11 @@ static void vti6_link_config(struct ip6_tnl *t) ...@@ -640,6 +641,11 @@ static void vti6_link_config(struct ip6_tnl *t)
else else
dev->flags &= ~IFF_POINTOPOINT; dev->flags &= ~IFF_POINTOPOINT;
if (keep_mtu && dev->mtu) {
dev->mtu = clamp(dev->mtu, dev->min_mtu, dev->max_mtu);
return;
}
if (p->flags & IP6_TNL_F_CAP_XMIT) { if (p->flags & IP6_TNL_F_CAP_XMIT) {
int strict = (ipv6_addr_type(&p->raddr) & int strict = (ipv6_addr_type(&p->raddr) &
(IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL)); (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL));
...@@ -656,20 +662,25 @@ static void vti6_link_config(struct ip6_tnl *t) ...@@ -656,20 +662,25 @@ static void vti6_link_config(struct ip6_tnl *t)
tdev = __dev_get_by_index(t->net, p->link); tdev = __dev_get_by_index(t->net, p->link);
if (tdev) if (tdev)
dev->mtu = max_t(int, tdev->mtu - dev->hard_header_len, mtu = tdev->mtu - sizeof(struct ipv6hdr);
IPV6_MIN_MTU); else
mtu = ETH_DATA_LEN - LL_MAX_HEADER - sizeof(struct ipv6hdr);
dev->mtu = max_t(int, mtu, IPV6_MIN_MTU);
} }
/** /**
* vti6_tnl_change - update the tunnel parameters * vti6_tnl_change - update the tunnel parameters
* @t: tunnel to be changed * @t: tunnel to be changed
* @p: tunnel configuration parameters * @p: tunnel configuration parameters
* @keep_mtu: MTU was set from userspace, don't re-compute it
* *
* Description: * Description:
* vti6_tnl_change() updates the tunnel parameters * vti6_tnl_change() updates the tunnel parameters
**/ **/
static int static int
vti6_tnl_change(struct ip6_tnl *t, const struct __ip6_tnl_parm *p) vti6_tnl_change(struct ip6_tnl *t, const struct __ip6_tnl_parm *p,
bool keep_mtu)
{ {
t->parms.laddr = p->laddr; t->parms.laddr = p->laddr;
t->parms.raddr = p->raddr; t->parms.raddr = p->raddr;
...@@ -679,11 +690,12 @@ vti6_tnl_change(struct ip6_tnl *t, const struct __ip6_tnl_parm *p) ...@@ -679,11 +690,12 @@ vti6_tnl_change(struct ip6_tnl *t, const struct __ip6_tnl_parm *p)
t->parms.proto = p->proto; t->parms.proto = p->proto;
t->parms.fwmark = p->fwmark; t->parms.fwmark = p->fwmark;
dst_cache_reset(&t->dst_cache); dst_cache_reset(&t->dst_cache);
vti6_link_config(t); vti6_link_config(t, keep_mtu);
return 0; return 0;
} }
static int vti6_update(struct ip6_tnl *t, struct __ip6_tnl_parm *p) static int vti6_update(struct ip6_tnl *t, struct __ip6_tnl_parm *p,
bool keep_mtu)
{ {
struct net *net = dev_net(t->dev); struct net *net = dev_net(t->dev);
struct vti6_net *ip6n = net_generic(net, vti6_net_id); struct vti6_net *ip6n = net_generic(net, vti6_net_id);
...@@ -691,7 +703,7 @@ static int vti6_update(struct ip6_tnl *t, struct __ip6_tnl_parm *p) ...@@ -691,7 +703,7 @@ static int vti6_update(struct ip6_tnl *t, struct __ip6_tnl_parm *p)
vti6_tnl_unlink(ip6n, t); vti6_tnl_unlink(ip6n, t);
synchronize_net(); synchronize_net();
err = vti6_tnl_change(t, p); err = vti6_tnl_change(t, p, keep_mtu);
vti6_tnl_link(ip6n, t); vti6_tnl_link(ip6n, t);
netdev_state_change(t->dev); netdev_state_change(t->dev);
return err; return err;
...@@ -804,7 +816,7 @@ vti6_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -804,7 +816,7 @@ vti6_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
} else } else
t = netdev_priv(dev); t = netdev_priv(dev);
err = vti6_update(t, &p1); err = vti6_update(t, &p1, false);
} }
if (t) { if (t) {
err = 0; err = 0;
...@@ -866,10 +878,8 @@ static void vti6_dev_setup(struct net_device *dev) ...@@ -866,10 +878,8 @@ static void vti6_dev_setup(struct net_device *dev)
dev->priv_destructor = vti6_dev_free; dev->priv_destructor = vti6_dev_free;
dev->type = ARPHRD_TUNNEL6; dev->type = ARPHRD_TUNNEL6;
dev->hard_header_len = LL_MAX_HEADER + sizeof(struct ipv6hdr);
dev->mtu = ETH_DATA_LEN;
dev->min_mtu = IPV6_MIN_MTU; dev->min_mtu = IPV6_MIN_MTU;
dev->max_mtu = IP_MAX_MTU; dev->max_mtu = IP_MAX_MTU - sizeof(struct ipv6hdr);
dev->flags |= IFF_NOARP; dev->flags |= IFF_NOARP;
dev->addr_len = sizeof(struct in6_addr); dev->addr_len = sizeof(struct in6_addr);
netif_keep_dst(dev); netif_keep_dst(dev);
...@@ -905,7 +915,7 @@ static int vti6_dev_init(struct net_device *dev) ...@@ -905,7 +915,7 @@ static int vti6_dev_init(struct net_device *dev)
if (err) if (err)
return err; return err;
vti6_link_config(t); vti6_link_config(t, true);
return 0; return 0;
} }
...@@ -1010,7 +1020,7 @@ static int vti6_changelink(struct net_device *dev, struct nlattr *tb[], ...@@ -1010,7 +1020,7 @@ static int vti6_changelink(struct net_device *dev, struct nlattr *tb[],
} else } else
t = netdev_priv(dev); t = netdev_priv(dev);
return vti6_update(t, &p); return vti6_update(t, &p, tb && tb[IFLA_MTU]);
} }
static size_t vti6_get_size(const struct net_device *dev) static size_t vti6_get_size(const struct net_device *dev)
......
...@@ -26,6 +26,12 @@ struct xfrm_trans_tasklet { ...@@ -26,6 +26,12 @@ struct xfrm_trans_tasklet {
}; };
struct xfrm_trans_cb { struct xfrm_trans_cb {
union {
struct inet_skb_parm h4;
#if IS_ENABLED(CONFIG_IPV6)
struct inet6_skb_parm h6;
#endif
} header;
int (*finish)(struct net *net, struct sock *sk, struct sk_buff *skb); int (*finish)(struct net *net, struct sock *sk, struct sk_buff *skb);
}; };
......
...@@ -285,8 +285,9 @@ void xfrm_local_error(struct sk_buff *skb, int mtu) ...@@ -285,8 +285,9 @@ void xfrm_local_error(struct sk_buff *skb, int mtu)
return; return;
afinfo = xfrm_state_get_afinfo(proto); afinfo = xfrm_state_get_afinfo(proto);
if (afinfo) if (afinfo) {
afinfo->local_error(skb, mtu); afinfo->local_error(skb, mtu);
rcu_read_unlock(); rcu_read_unlock();
}
} }
EXPORT_SYMBOL_GPL(xfrm_local_error); EXPORT_SYMBOL_GPL(xfrm_local_error);
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