ip6gre_changelink_common() calls ip6gre_tunnel_locate(), which only looks for ARPHRD_IP6GRE devices. The same changelink helper also handles ip6gretap and ip6erspan devices. This lets an L2 tunnel change its parameters to match another L2 tunnel, since the duplicate check looks for an L3 device instead. Incoming packets can then be delivered to the wrong interface. An L3 tunnel with matching parameters can also make a valid L2 update fail with EEXIST. Use ip6gre_tunnel_find() with dev->type, as the newlink paths do. Found while comparing the duplicate checks in newlink and changelink. Confirmed with ip link commands. For example, with an IPv6 underlay named under already configured: ip link add tap1 type ip6gretap local fd26:106::1 \ remote fd26:106::2 key 100 dev under ip link add tap2 type ip6gretap local fd26:106::1 \ remote fd26:106::2 key 200 dev under ip link set tap1 up ip link set tap2 up ip link set tap2 type ip6gretap key 100 Before the fix, the last command succeeds and received frames move from tap1 to tap2. After the fix, it fails with EEXIST and tap2 is unchanged. Tested with standalone namespace tests in UML, with three runs each for ip6gretap and ip6erspan, and with L3 GRE IPv4/IPv6 traffic and normal tunnel updates. Full x86_64 W=1 builds with adjusted configurations completed before and after with no new diagnostics. Fixes: c12b395a4664 ("gre: Support GRE over IPv6") Cc: stable@vger.kernel.org Signed-off-by: Xia Yan --- Runtime and build tests used net 7076f684d513. The target file is identical at the current base. Kernel selftests were not run. The allmodconfig- and allyesconfig-derived builds had WERROR, KASAN and KCSAN off. The allyesconfig-derived build also had KUNIT_ALL_TESTS, MCTP_TEST and MCTP_TRANSPORT_USBLIB_TEST off to avoid an existing MCTP test assertion. olddefconfig dropped IWLWIFI_KUNIT_TESTS when KUNIT_ALL_TESTS was disabled. net/ipv6/ip6_gre.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index b5d6ed8f0c369..df490798355de 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -2055,7 +2055,7 @@ ip6gre_changelink_common(struct net_device *dev, struct nlattr *tb[], ip6gre_netlink_parms(data, p_p); - t = ip6gre_tunnel_locate(net, p_p, 0); + t = ip6gre_tunnel_find(net, p_p, dev->type); if (t) { if (t->dev != dev) base-commit: 5d7f3375cd574fc83f0cd30839b21455c0e79ae2