@@ -1562,11 +1562,22 @@ static void ip6_tnl_update(struct ip6_tnl *t, struct __ip6_tnl_parm *p)
15621562 netdev_state_change (t -> dev );
15631563}
15641564
1565- static void ip6_tnl0_update (struct ip6_tnl * t , struct __ip6_tnl_parm * p )
1565+ static int ip6_tnl0_update (struct ip6_tnl * t , struct __ip6_tnl_parm * p ,
1566+ bool strict )
15661567{
1567- /* for default tnl0 device allow to change only the proto */
1568+ /* For the default ip6tnl0 device, allow changing only the protocol
1569+ * (the IP6_TNL_F_CAP_PER_PACKET flag is set on ip6tnl0, and all other
1570+ * parameters are 0).
1571+ */
1572+ if (strict &&
1573+ (!ipv6_addr_any (& p -> laddr ) || !ipv6_addr_any (& p -> raddr ) ||
1574+ p -> flags != t -> parms .flags || p -> hop_limit || p -> encap_limit ||
1575+ p -> flowinfo || p -> link || p -> fwmark || p -> collect_md ))
1576+ return - EINVAL ;
1577+
15681578 t -> parms .proto = p -> proto ;
15691579 netdev_state_change (t -> dev );
1580+ return 0 ;
15701581}
15711582
15721583static void
@@ -1680,7 +1691,7 @@ ip6_tnl_siocdevprivate(struct net_device *dev, struct ifreq *ifr,
16801691 } else
16811692 t = netdev_priv (dev );
16821693 if (dev == ip6n -> fb_tnl_dev )
1683- ip6_tnl0_update (t , & p1 );
1694+ ip6_tnl0_update (t , & p1 , false );
16841695 else
16851696 ip6_tnl_update (t , & p1 );
16861697 }
@@ -2053,8 +2064,28 @@ static int ip6_tnl_changelink(struct net_device *dev, struct nlattr *tb[],
20532064 struct ip6_tnl_net * ip6n = net_generic (net , ip6_tnl_net_id );
20542065 struct ip_tunnel_encap ipencap ;
20552066
2056- if (dev == ip6n -> fb_tnl_dev )
2057- return - EINVAL ;
2067+ if (dev == ip6n -> fb_tnl_dev ) {
2068+ if (ip_tunnel_netlink_encap_parms (data , & ipencap )) {
2069+ /* iproute2 always sets TUNNEL_ENCAP_FLAG_CSUM6, so
2070+ * let's ignore this flag.
2071+ */
2072+ ipencap .flags &= ~TUNNEL_ENCAP_FLAG_CSUM6 ;
2073+ if (memchr_inv (& ipencap , 0 , sizeof (ipencap ))) {
2074+ NL_SET_ERR_MSG (extack ,
2075+ "Only protocol can be changed for fallback tunnel, not encap params" );
2076+ return - EINVAL ;
2077+ }
2078+ }
2079+
2080+ ip6_tnl_netlink_parms (data , & p );
2081+ if (ip6_tnl0_update (t , & p , true) < 0 ) {
2082+ NL_SET_ERR_MSG (extack ,
2083+ "Only protocol can be changed for fallback tunnel" );
2084+ return - EINVAL ;
2085+ }
2086+
2087+ return 0 ;
2088+ }
20582089
20592090 if (ip_tunnel_netlink_encap_parms (data , & ipencap )) {
20602091 int err = ip6_tnl_encap_setup (t , & ipencap );
0 commit comments