Re: [PATCH net v3 2/2] ip6: vti: Use ip6_tnl.net in vti6_siocdevprivate().

From: Maoyi Xie

Date: Fri May 22 2026 - 07:06:01 EST


Hi Xiao,

You are right. I wrote a PoC and confirmed it on v4.

I used the same setup as the v4 test, just swapped the
SIOCCHGTUNNEL ioctl for `ip link set <name> type vti6 remote X
local Y` from inside the migrated netns. The ip command sends
RTM_NEWLINK with IFLA_INFO_DATA and no IFLA_LINK_NETNSID, so
rtnl_newlink() only checks the attacker's own user_ns. The
message lands in vti6_changelink(), vti6_update() inserts the
device into init_net's hash, and a SIOCGETTUNNEL in init_net for
the new params resolves to the migrated device. The primitive is
the same one v4 2/2 closes for the ioctl path. Only the entry
point differs.

For a fix I tried a small hunk in __rtnl_newlink(), before the
rtnl_changelink() dispatch. The hunk derives the link netns
through dev->rtnl_link_ops->get_link_net() when that callback
exists. If the link netns differs from tgt_net, it requires
netlink_ns_capable() against link_net->user_ns. I put it there
instead of in vti6_changelink() because the same gap applies to
other link_types with get_link_net (ipip, gre, sit, ip6_tnl),
and one site covers them all. link_types without get_link_net
would see no behaviour change.

I re-ran the PoC on v4 with that hunk applied. It returns
"Operation not permitted" and init_net's hash is unchanged.

I'd like to send this as a follow-up after v4 lands, since the
fix lives in net/core/rtnetlink.c rather than in vti6. v4 would
stay scoped to the ioctl path. Would that work for you?

Thanks again,
Maoyi