if_vlan: handle VID conflicts

If we fail to change the vlan id we have to undo the removal (and vlan id
change) in the error path. Otherwise we'll have removed the vlan object from the
hash table, and have the wrong vlan id as well. Subsequent modification attempts
will then try to remove an entry which doesn't exist, and panic.

Undo the vlan id modification if the insertion in the hash table fails, and
re-insert it under the original vlan id.

PR:		279195
Reviewed by:	zlei
MFC atfer:	1 week
Sponsored by:	Rubicon Communications, LLC ("Netgate")
Differential Revision:	https://reviews.freebsd.org/D45285
This commit is contained in:
Kristof Provost 2024-05-21 13:31:13 +02:00
parent 6e824f3713
commit bdd12889ea
2 changed files with 47 additions and 0 deletions

View File

@ -1715,10 +1715,20 @@ vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t vid,
ifv->ifv_proto = proto;
if (ifv->ifv_vid != vid) {
int oldvid = ifv->ifv_vid;
/* Re-hash */
vlan_remhash(trunk, ifv);
ifv->ifv_vid = vid;
error = vlan_inshash(trunk, ifv);
if (error) {
int ret __diagused;
ifv->ifv_vid = oldvid;
/* Re-insert back where we found it. */
ret = vlan_inshash(trunk, ifv);
MPASS(ret == 0);
}
}
/* Will unlock */
goto done;

View File

@ -297,6 +297,42 @@ bpf_pcp_cleanup()
vnet_cleanup
}
atf_test_case "conflict_id" "cleanup"
conflict_id_head()
{
atf_set descr 'Test conflicting VLAN IDs, PR #279195'
atf_set require.user root
}
conflict_id_body()
{
vnet_init
epair=$(vnet_mkepair)
vnet_mkjail alcatraz ${epair}b
vlan_a=$(jexec alcatraz ifconfig vlan create)
vlan_b=$(jexec alcatraz ifconfig vlan create)
jexec alcatraz ifconfig ${vlan_a} vlan 100 vlandev ${epair}b
jexec alcatraz ifconfig ${vlan_b} vlan 101 vlandev ${epair}b
atf_check -s exit:1 -o ignore -e ignore \
jexec alcatraz ifconfig ${vlan_a} vlan 101
atf_check -s exit:0 -o match:"vlan: 100" \
jexec alcatraz ifconfig ${vlan_a}
atf_check -s exit:0 -o ignore -e ignore \
jexec alcatraz ifconfig ${vlan_a} vlan 100
}
conflict_id_cleanup()
{
vnet_cleanup
}
atf_init_test_cases()
{
atf_add_test_case "basic"
@ -306,4 +342,5 @@ atf_init_test_cases()
atf_add_test_case "qinq_dot"
atf_add_test_case "qinq_setflags"
atf_add_test_case "bpf_pcp"
atf_add_test_case "conflict_id"
}