>Number:         185619
>Category:       kern
>Synopsis:       [VNET] Name conflict not checked when a child vnet goes away 
>and returns its interface(s) back to the parent
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Jan 09 22:30:00 UTC 2014
>Closed-Date:
>Last-Modified:
>Originator:     Eugene M. Kim
>Release:        11-CURRENT
>Organization:
AstralBlue
>Environment:
FreeBSD hydrogen.astralblue.net 11.0-CURRENT FreeBSD 11.0-CURRENT #1 r260314: 
Sun Jan  5 17:53:02 UTC 2014     
r...@hydrogen.astralblue.net:/usr/obj/usr/src/sys/GENERIC-IPSEC-VIMAGE  amd64

>Description:
Each vnet has its own namespace for network interfaces.  As a result, two 
network interfaces may have the same name if they belong to distinct vnets.

When one of these interfaces tries to move into the other's vnet, the name 
conflict should - and does - block the operation, except in one case: When a 
child vnet goes away and returns its interfaces to its parent vnet, the name 
conflict is not checked and the parent vnet ends up having both interfaces of 
the same name.  This confuses various tools such as ifconfig(8).
>How-To-Repeat:
The first scenario shown below renames two epair(4) interfaces as "jnet" (one 
renamed in a parent vnet, another renamed in a child vnet), then destroys the 
child vnet to bring its jnet interface back to the parent.  ifconfig(8) output 
merges these two interfaces into one block (shown by two MAC addresses).

root@hydrogen:~ # jail -c name=test vnet persist
root@hydrogen:~ # ifconfig epair create
epair0a
root@hydrogen:~ # ifconfig epair0a
epair0a: flags=8842<BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=8<VLAN_MTU>
        ether 02:ff:40:00:04:0a
        nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
        media: Ethernet 10Gbase-T (10Gbase-T <full-duplex>)
        status: active
root@hydrogen:~ # ifconfig epair0b
epair0b: flags=8842<BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=8<VLAN_MTU>
        ether 02:ff:90:00:05:0b
        nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
        media: Ethernet 10Gbase-T (10Gbase-T <full-duplex>)
        status: active
root@hydrogen:~ # ifconfig epair0a name jnet
root@hydrogen:~ # ifconfig epair0b vnet test
root@hydrogen:~ # jexec test ifconfig epair0b name jnet
root@hydrogen:~ # jail -r test
root@hydrogen:~ # ifconfig
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
        options=600003<RXCSUM,TXCSUM,RXCSUM_IPV6,TXCSUM_IPV6>
        inet6 ::1 prefixlen 128 
        inet6 fe80::1%lo0 prefixlen 64 scopeid 0x3 
        inet 127.0.0.1 netmask 0xff000000 
        nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
jnet: flags=8842<BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=8<VLAN_MTU>
        ether 02:ff:40:00:04:0a
        ether 02:ff:90:00:05:0b
        nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
        media: Ethernet 10Gbase-T (10Gbase-T <full-duplex>)
        status: active
root@hydrogen:~ # ifconfig jnet destroy
root@hydrogen:~ # 

The second scenario shown below creates two vnets and two epair(4) pairs (one 
pair for each vnet), injects the "b" end of each pair into the corresponding 
vnet then renames it as "jnet", then destroys the two vnets, showing the parent 
vnet ending up with both jnet interfaces.  At the end, "ifconfig jnet destroy" 
can be done twice: The first command picks and destroys one of the two pairs.

root@hydrogen:~ # ifconfig epair create
epair0a
root@hydrogen:~ # ifconfig epair create
epair1a
root@hydrogen:~ # jail -c name=test1 vnet persist
root@hydrogen:~ # jail -c name=test2 vnet persist
root@hydrogen:~ # ifconfig epair0b vnet test1
root@hydrogen:~ # jexec test1 ifconfig epair0b name jnet
root@hydrogen:~ # ifconfig epair1b vnet test2
root@hydrogen:~ # jexec test2 ifconfig epair1b name jnet
root@hydrogen:~ # jail -r test1
root@hydrogen:~ # jail -r test2
root@hydrogen:~ # ifconfig 
em0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        
options=4219b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,TSO4,WOL_MAGIC,VLAN_HWTSO>
        ether 74:d0:2b:13:66:fc
        inet 10.0.0.11 netmask 0xffffff00 broadcast 10.0.0.255 
        inet6 fe80::76d0:2bff:fe13:66fc%em0 prefixlen 64 scopeid 0x1 
        inet6 2001:470:1f05:155:76d0:2bff:fe13:66fc prefixlen 64 autoconf 
        inet6 2002:43bc:72e6:1:76d0:2bff:fe13:66fc prefixlen 64 autoconf 
        nd6 options=23<PERFORMNUD,ACCEPT_RTADV,AUTO_LINKLOCAL>
        media: Ethernet autoselect (1000baseT <full-duplex>)
        status: active
em1: flags=8c02<BROADCAST,OACTIVE,SIMPLEX,MULTICAST> metric 0 mtu 1500
        
options=4219b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,TSO4,WOL_MAGIC,VLAN_HWTSO>
        ether 74:d0:2b:13:6b:43
        nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
        media: Ethernet autoselect
        status: no carrier
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
        options=600003<RXCSUM,TXCSUM,RXCSUM_IPV6,TXCSUM_IPV6>
        inet6 ::1 prefixlen 128 
        inet6 fe80::1%lo0 prefixlen 64 scopeid 0x3 
        inet 127.0.0.1 netmask 0xff000000 
        nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
epair0a: flags=8842<BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=8<VLAN_MTU>
        ether 02:ff:40:00:04:0a
        nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
        media: Ethernet 10Gbase-T (10Gbase-T <full-duplex>)
        status: active
epair1a: flags=8842<BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=8<VLAN_MTU>
        ether 02:ff:40:00:06:0a
        nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
        media: Ethernet 10Gbase-T (10Gbase-T <full-duplex>)
        status: active
jnet: flags=8842<BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=8<VLAN_MTU>
        ether 02:ff:90:00:05:0b
        ether 02:ff:90:00:07:0b
        nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
        media: Ethernet 10Gbase-T (10Gbase-T <full-duplex>)
        status: active
root@hydrogen:~ # ifconfig jnet destroy
root@hydrogen:~ # ifconfig jnet destroy
root@hydrogen:~ # 

>Fix:
One of the following would fix the problem (among other approaches I cannot 
think of):

Option 1: Give the returned interface a random, unique name.

Option 2: When injecting an interface into a child vnet, leave a "shadow" of 
its name in the parent vnet.  Don't let other interfaces in the parent vnet 
take the shadowed name, and give the shadowed name to the moved interface when 
it returns from the child vnet.

Option 3: Block destruction of a vnet if doing so would cause a name conflict 
in the parent vnet.

Option 3 opens a bigger problem and is probably impractical, as such blocking 
should be cascaded to and handled by the triggering event such as jail 
destruction, blocking which is probably a bad idea.

Option 1 is simpler, but the resulting behavior is random/nondeterministic and 
makes interface tracking harder.

Option 2 is more predictable and deterministic, at the cost of more complex 
implementation.  And it doesn't cover the case of pseudo-interfaces created 
locally inside a vnet, because such interfaces have no shadowed name in the 
parent vnet; falling back to option 1 would be one way to solve this.

>Release-Note:
>Audit-Trail:
>Unformatted:
_______________________________________________
freebsd-bugs@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
To unsubscribe, send any mail to "freebsd-bugs-unsubscr...@freebsd.org"

Reply via email to