linux
Fail to process a VLAN packet without VLAN support
When the kernel is not configured to support VLANs and we receive a tagged VLAN packet through a network interface, eventually vlan_hwaccel_do_receive() is called even if VLAN support is disabled---and thus we reach a BUG().
Bug fixed by commit 0988c4c7fb5
| Type | FatalAssertionViolation |
| Config | "!VLAN_8021Q" (1st degree) |
| Fix-in | code |
| Location | include/linux/ |
#include <assert.h>
// To avoid constant propagation
__attribute__ ((noinline)) int nondet() { return 42; }
#ifdef CONFIG_VLAN_8021Q
_Bool vlan_hwaccel_do_receive()
{
// do something
return 1;
}
#else
_Bool vlan_hwaccel_do_receive()
{
assert(0); // (4) ERROR
return 0;
}
#endif
int __netif_receive_skb()
{
if (nondet())
{
vlan_hwaccel_do_receive(); // (3)
}
return 0;
}
int netif_receive_skb()
{
#ifdef CONFIG_RPS
return __netif_receive_skb(); // (2)
#else
return __netif_receive_skb(); // (2)
#endif
}
int main(void)
{
netif_receive_skb(); // (1)
return 0;
}
diff --git a/simple/0988c4c.c b/simple/0988c4c.c
--- a/simple/0988c4c.c
+++ b/simple/0988c4c.c
@@ -13,7 +13,6 @@
#else
_Bool vlan_hwaccel_do_receive()
{
- assert(0); // (4) ERROR
return 0;
}
#endif
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
int main(int argc, char** argv)
{
// netif_receive_skb();
if (rand() % 2) {
#ifdef CONFIG_VLAN_8021Q
// do something
return true;
#else
assert(false); // ERROR
return false;
#endif
}
return 0;
}
. call net/core/dev.c:2602:netif_rx()
// reads a packet from a device driver and queues it to be processed by upper layers
// at some point netif_receive_skb() will be invoked ...
. call net/core/dev.c:3039:netif_receive_skb()
. 3067: return __netif_receive_skb(skb);
.. call net/core/dev.c:2887:__netif_receive_skb()
.. 2972: if (vlan_tx_tag_present(skb)) {
.. 2977: if (vlan_hwaccel_do_receive(&skb)) {
... [!VLAN_8021Q] call include/linux/if_vlan.h:169:vlan_hwaccel_do_receive()
... ERROR [!VLAN_8021Q] BUG();