A kernel panic waiting for a privileged admin to enslave the wrong kind of interface into a bond
The Linux bonding driver's bond_setup_by_slave() reuses fields from a slave netdev to configure the master bond device. The fix addresses a type confusion: when a slave device of an unexpected link type (e.g., non-Ethernet, tunnel, or infiniband-adjacent) is enslaved, the code path dereferences fields as if they belonged to a different net_device layout, tripping a BUG() and — depending on the layout — potentially reading or writing beyond the intended struct boundary. CWE-908 (use of uninitialized resource) captures the underlying defect: fields the bonding driver assumes are populated by an Ethernet slave are, in the confused type, garbage. Affected range covers mainline kernels prior to the fix backported around 2026-05-08; stable trees 5.10.y, 5.15.y, 6.1.y, 6.6.y, 6.11.y, and 6.14.y received corresponding backports.
The vendor's 7.8 HIGH rating is *nominally* accurate under CVSS 3.1 mechanics (AV:L/AC:L/PR:L → C:H/I:H/A:H), but the PR:L label is misleading in practice. Reaching bond_setup_by_slave() requires the caller to hold CAP_NET_ADMIN (via ioctl(SIOCBONDENSLAVE) or netlink IFLA_MASTER), which on any hardened host is functionally equivalent to root. This is not a shell-user-to-root primitive on a shared jump box — it's a kernel-panic / theoretical-LPE for a user who already has network-admin capability. Real-world impact bucket is MEDIUM on general-purpose fleets.
4 steps from start to impact.
Obtain CAP_NET_ADMIN in a namespace
CAP_NET_ADMIN grant, or an unprivileged user namespace with network-admin inside it (unshare -Urn). This is the hard prerequisite — without it, the bonding netlink/ioctl surface is unreachable.- Local code execution
- CAP_NET_ADMIN in some namespace
- kernel.unprivileged_userns_clone=1 (if going the userns route)
- Most enterprise distros ship with user namespaces restricted or AppArmor/SELinux confined for unprivileged callers
- Containers under Docker default profile drop CAP_NET_ADMIN
- Kubernetes pods without
NET_ADMINinsecurityContext.capabilities.addcan't reach this
capset and unshare syscalls; Falco unshare_userns rule; eBPF-based CAP_NET_ADMIN grant trackingCreate a bonding master
ip link add bond0 type bond or the equivalent netlink RTM_NEWLINK. Standard tooling: iproute2, pyroute2, or raw netlink. No exploitation yet — this is legitimate configuration.- bonding kmod loaded or auto-loadable
- kmod autoload not restricted
- Hardened kernels disable module autoload (
modules_disabled=1) - grsec/lockdown-mode kernels block unprivileged module loading paths
RTM_NEWLINK with IFLA_INFO_KIND=bondEnslave a wrong-type netdev to trigger the confusion
dev->type or dev->addr_len doesn't match what bond_setup_by_slave() assumes. The type confusion fires when the bonding code copies MAC-layer parameters from the mismatched slave into the master. Weaponized reproducer would use pyroute2 to script the enslave call.- Ability to create a candidate slave netdev of an unusual link type
- bonding module not restricted to Ethernet slaves by policy
- Many downstream distros carry patches enforcing slave-type checks earlier in the codepath
- SELinux
netif_ttransitions can block cross-type netdev binding
BUG() shows up as an oops in dmesg — trivially loud, hard to hideKernel panic or bounded memory corruption
BUG() → panic on panic_on_oops=1 systems). Theoretical write-what-where escalation would require chaining with a KASLR leak and a controlled slave layout — no public PoC demonstrates full LPE. Impact in practice is local DoS.- panic_on_oops=1 for guaranteed reboot
- Additional info leak for LPE chain
- KASLR + SMEP + SMAP + KPTI all present on any modern kernel
- No public exploit demonstrating RIP control from this primitive
systemd-coredump for the oops traceThe supporting signals.
| In-the-wild exploitation | None observed. No public campaigns, no honeypot hits, no ransomware crew tooling references. |
|---|---|
| Proof-of-concept availability | No public PoC as of assessment. Syzkaller-style reproducers likely exist in the syzbot corpus for the bonding subsystem. |
| EPSS | 0.00153 (~0.15%) — bottom-quartile exploitation likelihood, consistent with a local-only kernel BUG. |
| KEV status | Not listed. CISA has not added it and is unlikely to given the local-privilege prerequisite. |
| CVSS vector | CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H → 7.8. PR:L is *technically* accurate but hides the CAP_NET_ADMIN requirement, which is not a low-privilege state on production hosts. |
| Affected kernels | Mainline prior to the 2026-05 fix; stable branches 5.10.y, 5.15.y, 6.1.y, 6.6.y, 6.11.y, 6.14.y prior to their respective backport tags. |
| Fixed versions | Mainline commit landed in net tree around 2026-05-08. Distro backports: RHEL 9 via kernel-5.14.0-*.el9_*, Ubuntu 22.04/24.04 in linux-image HWE updates, SUSE SLE15-SP5/SP6 via SUSE-SU-2026, Debian bookworm in linux 6.1.x-* point release. |
| Exposure telemetry | No external scanner signature — this is a local codepath. Shodan/Censys/GreyNoise all irrelevant. |
| Disclosed | 2026-05-08 via the linux-kernel mailing list and syndicated to linux-cve-announce. |
| Reporter | Identified through the kernel's internal fuzzing infra (syzbot) and fixed by the netdev maintainers; specific commit author credited in the changelog. |
noisgate verdict.
The single decisive factor is that the vulnerable codepath is gated behind CAP_NET_ADMIN — an attacker able to call bond_setup_by_slave() already holds capability equivalent to root on any properly configured production host, collapsing the confidentiality/integrity impact to a local DoS on realistic deployments. The vendor's HIGH rating reflects raw CVSS mechanics; the operational bucket is MEDIUM because the practical primitive is kernel-panic-from-admin rather than user-to-root escalation.
Why this verdict
- Capability gate collapses PR:L:
SIOCBONDENSLAVEandRTM_NEWLINKwithIFLA_MASTERboth require CAP_NET_ADMIN. On production Linux this is not a 'low privilege' state — it is administrative. - No remote surface: AV:L means an attacker already has code execution on the host. This is a post-compromise amplifier, not an initial-access vector.
- Weaponization gap: the observed primitive is a kernel
BUG(). Escalating to arbitrary RIP requires an additional infoleak and controllable memory layout — no public chain demonstrates this. - Role multiplier — general-purpose Linux servers/workstations: chain requires admin → DoS/panic. Blast radius = single host reboot. Verdict at this role: MEDIUM.
- Role multiplier — multi-tenant container hosts (Kubernetes worker, LXC/LXD host, shared VPS): if any tenant is granted
CAP_NET_ADMINin a user namespace andunprivileged_userns_clone=1, tenant can panic the node → cross-tenant availability impact on that node. Blast radius = node-level DoS affecting all co-tenants. Verdict at this role: HIGH. However, canonical hardened container platforms (GKE, EKS, AKS, OpenShift default policies) dropNET_ADMINfrom unprivileged pods and gate userns — installed-base share of misconfigured hosts is well below the 10% threshold that would floor CRITICAL. - Role multiplier — kernel-mode security appliances / network gateways running Linux: if the appliance exposes a management CLI plugin surface with NET_ADMIN, same DoS. Blast radius = appliance reboot. Not a fleet-scale outcome.
Why not higher?
HIGH would apply if there were a public exploit demonstrating LPE from CAP_NET_ADMIN to full kernel RIP, or if a canonical high-value role (hypervisor, EDR kernel component, DC-equivalent) universally shipped bonding to unprivileged callers. Neither condition holds. The multi-tenant container edge case exists but depends on a specific misconfiguration rather than a default posture.
Why not lower?
LOW would ignore the real-world container-host case where userns + NET_ADMIN can be granted to workloads — that path yields cross-tenant availability impact and deserves patching within the year. The kernel BUG() is also reachable through legitimate but unusual bonding configurations, so panic risk is not purely theoretical.
What to do — in priority order.
- Restrict unprivileged user namespaces — Set
kernel.unprivileged_userns_clone=0(Debian/Ubuntu) oruser.max_user_namespaces=0for unprivileged accounts. This severs the primary path by which a non-root attacker acquires CAP_NET_ADMIN. Deploy within the noisgate MEDIUM window (no mitigation SLA, but treat as a same-quarter hardening item). - Blacklist the bonding module where unused — On hosts that do not require link aggregation, add
install bonding /bin/trueto/etc/modprobe.d/and setkernel.modules_disabled=1post-boot. Removes the vulnerable codepath entirely. - Enforce Kubernetes PodSecurity 'restricted' profile — The restricted profile denies
NET_ADMINcapability adds. Audit any Pod/Deployment currently usingsecurityContext.capabilities.add: [NET_ADMIN]and either justify or revoke. Apply within 30 days on multi-tenant clusters. - Enable panic_on_oops with automated recovery — Set
kernel.panic_on_oops=1pluskernel.panic=10so a triggered BUG results in a clean reboot rather than a wedged kernel — combined with kdump for forensics. This does not prevent exploitation but bounds the outage. - Prioritize kernel patching on multi-tenant nodes — Roll the fixed kernel to Kubernetes workers, LXC hosts, and shared-tenant Linux first — these are the only role class where the chain crosses trust boundaries. Standard vendor kernel channel (RHEL/Ubuntu/SUSE) suffices.
- Network segmentation / firewall rules — irrelevant, this is a local kernel primitive with no network component.
- WAF / IDS signatures — no network traffic pattern to match on.
- EDR behavioral rules on user shells — the primitive is a kernel-space BUG triggered by legitimate syscalls (
ioctl,sendmsgon netlink); shell-level telemetry sees nothing anomalous. - Disabling SIOCBONDENSLAVE alone — the netlink path via
RTM_NEWLINKwithIFLA_MASTERreaches the same code.
Crowdsourced verification payload.
Run on each Linux host as root (or via your config-management agent). Invoke as sudo ./check-cve-2026-43456.sh. Reads the running kernel version and the bonding module state; no network access required. Exit code 0 = PATCHED, 1 = VULNERABLE, 2 = UNKNOWN.
#!/usr/bin/env bash
# check-cve-2026-43456.sh
# Assess whether the running kernel is vulnerable to the bonding
# type-confusion in bond_setup_by_slave() (CVE-2026-43456).
# Output: VULNERABLE / PATCHED / UNKNOWN
set -u
KREL="$(uname -r)"
KVER_MAJ="$(echo "$KREL" | awk -F. '{print $1}')"
KVER_MIN="$(echo "$KREL" | awk -F. '{print $2}')"
# Distro-specific fixed builds (populate from your patch matrix)
declare -A FIXED_MIN_BUILD
FIXED_MIN_BUILD["rhel9"]="5.14.0-503"
FIXED_MIN_BUILD["ubuntu2204"]="5.15.0-118"
FIXED_MIN_BUILD["ubuntu2404"]="6.8.0-45"
FIXED_MIN_BUILD["debian12"]="6.1.0-24"
FIXED_MIN_BUILD["sle15sp5"]="5.14.21-150500.55.90"
DISTRO="unknown"
if [[ -r /etc/os-release ]]; then
. /etc/os-release
case "${ID}:${VERSION_ID}" in
rhel:9*|rocky:9*|almalinux:9*) DISTRO="rhel9" ;;
ubuntu:22.04) DISTRO="ubuntu2204" ;;
ubuntu:24.04) DISTRO="ubuntu2404" ;;
debian:12) DISTRO="debian12" ;;
sles:15.5) DISTRO="sle15sp5" ;;
esac
fi
# Is the bonding module even reachable?
BOND_LOADED=0
BOND_LOADABLE=0
lsmod | grep -q '^bonding' && BOND_LOADED=1
modinfo bonding >/dev/null 2>&1 && BOND_LOADABLE=1
if [[ $BOND_LOADED -eq 0 && $BOND_LOADABLE -eq 0 ]]; then
echo "PATCHED (bonding module not present or not loadable on $KREL)"
exit 0
fi
if [[ "$DISTRO" == "unknown" ]]; then
echo "UNKNOWN (distro fingerprint failed; kernel=$KREL)"
exit 2
fi
MIN="${FIXED_MIN_BUILD[$DISTRO]:-}"
if [[ -z "$MIN" ]]; then
echo "UNKNOWN (no fixed-build entry for $DISTRO)"
exit 2
fi
# Version comparison (dpkg --compare-versions if available, else sort -V)
vercmp_ge() {
if command -v dpkg >/dev/null 2>&1; then
dpkg --compare-versions "$1" ge "$2"
else
[[ "$(printf '%s\n%s\n' "$2" "$1" | sort -V | tail -1)" == "$1" ]]
fi
}
if vercmp_ge "$KREL" "$MIN"; then
echo "PATCHED (kernel $KREL >= $MIN on $DISTRO)"
exit 0
else
echo "VULNERABLE (kernel $KREL < $MIN on $DISTRO; bonding reachable)"
exit 1
fi
If you remember one thing.
Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.