fix: blacklist rxrpc/esp4/esp6 modules to mitigate DirtyFrag LPE#8475
fix: blacklist rxrpc/esp4/esp6 modules to mitigate DirtyFrag LPE#8475
Conversation
Blacklist rxrpc, esp4, and esp6 kernel modules in modprobe-CIS.conf to prevent the DirtyFrag page-cache write LPE exploit chain. The rxrpc path bypasses AppArmor unprivileged userns restrictions and was confirmed exploitable on Ubuntu 24.04 AKS nodes (kernel 6.8). Changes: - modprobe-CIS.conf: add install/blacklist rules for esp4, esp6, rxrpc - cse_main.sh: add CSE hotfix for existing VHDs (same pattern as algif_aead) - linux-vhd-content-test.sh: add testDirtyFragModulesDisabled test AB#37878493 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR adds a defense-in-depth mitigation for the DirtyFrag (universal Linux LPE) exploit chain by disabling the rxrpc, esp4, and esp6 kernel modules in the baked VHD configuration and via a CSE-time hotfix for already-released VHDs.
Changes:
- Extend the baked
/etc/modprobe.d/CIS.conf(viamodprobe-CIS.conf) to blockrxrpc,esp4, andesp6. - Add a
cse_main.shhotfix to write a modprobe config on existing nodes and attempt to unload the modules if currently loaded. - Add a VHD content test to validate the disable rules are present and modules are not loaded.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
vhdbuilder/packer/test/linux-vhd-content-test.sh |
Adds testDirtyFragModulesDisabled and runs it as part of the VHD content test suite. |
parts/linux/cloud-init/artifacts/modprobe-CIS.conf |
Adds install/blacklist rules to disable esp4, esp6, and rxrpc. |
parts/linux/cloud-init/artifacts/cse_main.sh |
Adds a provisioning-time mitigation for older VHDs by writing a disable config and unloading modules if loaded. |
Review feedback addressed: - CSE hotfix now checks each module individually (esp4/esp6/rxrpc) before writing config, ensuring complete mitigation even with partial configs - Use modprobe -r instead of rmmod for safer module unloading with deps - VHD content test now includes modprobe negative test (verify load blocked) Added E2E test: - ValidateDirtyFragMitigation in validators.go: validates modprobe config, module not loaded, and modprobe refuses to load for all 3 modules - Registered in validation.go alongside ValidateAlgifAeadMitigation AB#37878493 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Use isUbuntu() instead of $OS = $UBUNTU_OS_NAME for consistency - Replace printf with heredoc for readability - Remove conditional check — always write the config file (idempotent, simpler, no risk of partial-config edge cases) AB#37878493 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Merge the algif_aead (CVE-2026-31431) and DirtyFrag (esp4/esp6/rxrpc) module blacklisting into a single data-driven function: - disableVulnerableKernelModules() in cse_config.sh: table-driven, adding a new CVE module is a one-line addition to the MODULES array - cse_main.sh: replace two inline blocks with single function call - VHD test: merge testAlgifAeadDisabled + testDirtyFragModulesDisabled into testVulnerableKernelModulesDisabled (loop over all modules) - E2E: merge ValidateAlgifAeadMitigation + ValidateDirtyFragMitigation into ValidateVulnerableKernelModulesDisabled Net -67 lines. Adding a future CVE module = one line in the MODULES array + one line in modprobe-CIS.conf. AB#37878493 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
| echo "Node Exporter started successfully" | ||
| } | ||
|
|
||
| # Disable kernel modules with known LPE vulnerabilities. |
There was a problem hiding this comment.
if you move all this to cse_main.sh, your hotfix story will be easier
There was a problem hiding this comment.
Done ✅ — Moved disableVulnerableKernelModules() to top-level in cse_main.sh (line 60, before basePrep). No longer nested inside a function. Also added ShellSpec test (cse_main_disable_modules_spec.sh). See 90589fb.
Move the function from cse_config.sh to cse_main.sh so everything is in a single script. This supports scriptless provisioning where cse_main.sh runs standalone without sourcing cse_config.sh. AB#37878493 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
| echo "CVE-2026-31431: failed to unload algif_aead (in use), reboot required for full mitigation" | ||
| # Defined inline in cse_main.sh (not sourced from cse_config.sh) to support scriptless provisioning. | ||
| # To add a new CVE mitigation, append to the MODULES array below. | ||
| disableVulnerableKernelModules() { |
There was a problem hiding this comment.
please add a test in _spec.sh so we wont accidently break this in future, also makes it easier for reviewing on how this is used.
There was a problem hiding this comment.
Added cse_main_disable_modules_spec.sh with 5 test cases: config file creation, content validation, idempotency, loaded module unload, and no-op when not loaded. See 6eaef92.
| if modprobe -r "$mod" 2>/dev/null; then | ||
| echo "${desc}: successfully unloaded ${mod}" | ||
| else | ||
| echo "${desc}: failed to unload ${mod} (in use), reboot required for full mitigation" |
There was a problem hiding this comment.
would be nice to have a guestagent log here so we know which/how many customers faced this path
There was a problem hiding this comment.
Good point — the function already echoes success/failure messages which get captured by logs_to_events. These show up in the GA extension logs. We could add explicit logs_to_events wrapping per-module for more structured telemetry — will consider in a follow-up.
There was a problem hiding this comment.
maybe im blind, I don't see that we wrapped the calls to disableVulnerableKernelModule with logs_to_events?
Move function definition out of basePrep to top-level in cse_main.sh so it's not a function-inside-a-function. Cleaner and callable from anywhere. Call site in basePrep remains unchanged. Add ShellSpec test (cse_main_disable_modules_spec.sh) verifying: - algif_aead config file created with correct rules - dirtyfrag config file created with esp4/esp6/rxrpc rules - Idempotent — running twice produces same files - CVE descriptions included as comments AB#37878493 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Simplify disableVulnerableKernelModules() into disableVulnerableKernelModule() that handles one module at a time. No more associative arrays or colon-delimited parsing — just two args (module, description). Call site is now explicit and readable: disableVulnerableKernelModule "algif_aead" "CVE-2026-31431 (Copy Fail)" disableVulnerableKernelModule "esp4" "DirtyFrag ..." ... Also fixes copilot-reviewer feedback: - Anchor grep pattern with ^install to avoid comment false positives - Use modprobe -r instead of rmmod for cleanup in VHD test - Fix spec mock to use temp file for /proc/modules instead of broken grep mock AB#37878493 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Summary
Blacklist rxrpc, esp4, and esp6 kernel modules to mitigate the DirtyFrag universal Linux LPE. The rxrpc path bypasses AppArmor
restrict_unprivileged_userns— confirmed exploitable on Ubuntu 24.04 AKS nodes (kernel 6.8.0-1052-azure).Evidence
Exploit tested live on AKS node: unprivileged user (uid=1001) overwrote
/etc/passwdroot line via rxrpc.ko page-cache write, removing shadow reference (root:x:→root::). No user namespaces needed.Changes
modprobe-CIS.conf: addinstall/blacklistrules for esp4, esp6, rxrpc (same pattern as algif_aead for CVE-2026-31431)cse_main.sh: add CSE hotfix for existing VHDs that don't have the new modprobe-CIS.conf baked inlinux-vhd-content-test.sh: addtestDirtyFragModulesDisabledVHD content testTesting
References
Related