Open vSwitch (OVS) is a widely used virtual switch in Linux environments, especially for software-defined networking (SDN), virtualization, and cloud platforms. In 2021, a vulnerability was reported and subsequently resolved in the Linux kernel component supporting OVS, which could potentially allow an attacker to trigger a stack-based out-of-bounds (OOB) read when fragmenting IPv4 packets. This post explains the bug, how it can be triggered, and how it was fixed — in plain English.
The CVE Details
- CVE ID: CVE-2021-46955
Affected Software: Linux kernel (specifically Open vSwitch module)
- Vulnerable Kernel Versions: Before the fix in this commit, e.g. v5.12-rc6 and similar.
- Fixed in kernel: v5.12-rc7 and above
What’s the Issue?
When OVS needs to fragment IPv4 packets, it temporarily uses a struct dst_entry on the C stack. An IPv4-specific path in the kernel later treats this object as a struct rtable due to how routing and MTU (Maximum Transmission Unit) information is fetched. However, struct rtable is *bigger* than struct dst_entry and has more fields. That means reading past the end of the temporary stack buffer: stack out-of-bounds read.
This can happen when you, your container, or your VM triggers packet fragmentation using OVS.
Kernel AddressSanitizer (KASAN) Symptoms
If you run KASAN-enabled kernel, you might see stack OOB warnings such as:
BUG: KASAN: stack-out-of-bounds in ip_do_fragment+x1b03/x1f60
Read of size 1 at addr ffff888112fc713c by task handler2/1367
...with a call trace resembling
ip_do_fragment
ip_skb_dst_mtu
ip_dst_mtu_maybe_forward
ip_mtu_locked
Why is this Dangerous?
Stack OOB reads leak adjacent stack memory. While this particular bug seems not to allow direct code execution (it's a read, not a write), it:
The Code Path
Here's an (annotated) version of the problematic snippet. For IPv4, a temporary struct dst_entry is put on the stack.
Vulnerable OVS Code Fragment
/*
* Inside the OVS module (openvswitch/datapath.c)
* Function: ovs_fragment()
*/
struct dst_entry ovs_dst;
...
/* Use ovs_dst as a temporary destination */
skb_dst_set(skb, &ovs_dst);
/* Later */
ip_do_fragment(skb);
/* Inside ip_do_fragment() and transitively ip_skb_dst_mtu()... */
But! The kernel expects a struct rtable
static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst)
{
const struct rtable *rt = (const struct rtable *) dst;
if (ip_mtu_locked(rt))
return dst_mtu(dst);
...
}
ip_mtu_locked() reads a field only present in a full struct rtable
static inline bool ip_mtu_locked(const struct rtable *rt)
{
return rt->rt_mtu_locked;
}
This causes reading off the end of your local ovs_dst stack object, colliding with whatever is next on the stack (ovs_rt or other data).
The Stack Layout (from the bug)
this frame has 2 objects:
32, 144) 'ovs_dst'
[192, 424) 'ovs_rt'
Fixed Code Snippet
#ifdef HAVE_IPV6
struct rt6_info ovs_rt6;
#endif
#if IS_ENABLED(CONFIG_INET)
struct rtable ovs_rt;
#endif
struct dst_entry *ovs_dst;
/* ... */
#if IS_ENABLED(CONFIG_INET)
if (skb->protocol == htons(ETH_P_IP)) {
memset(&ovs_rt, , sizeof(ovs_rt));
ovs_dst = &ovs_rt.dst;
}
#endif
This makes sure the temporary on-stack object is large enough for all accesses.
Links & Further Reading
- CVE-2021-46955 @ NVD
- Upstream patch commit
- KASAN docs
- Original mailing list report
- Open vSwitch Homepage
Impact & Recommendations
While exploitation as a privilege escalation is unlikely in most settings, stack OOB reads in kernel code can be a springboard for more dangerous attacks, especially when KASAN or similar tools are not in use. Always run up-to-date kernels, especially in VPS, container, or cloud environments using Open vSwitch or any heavy virtual networking.
Check your kernel: If you use OVS and your kernel is older than May 2021, verify you have the fix for CVE-2021-46955!
*This summary was crafted for clarity and practical understanding. For your own code and systems, always check upstream references.*
Timeline
Published on: 02/27/2024 19:04:06 UTC
Last modified on: 12/06/2024 17:53:52 UTC