diff --git a/cfbs.json b/cfbs.json index 549f89d..7d7c609 100644 --- a/cfbs.json +++ b/cfbs.json @@ -142,6 +142,47 @@ "bundles delete_home_dotshosts:main" ] }, + "dirtyfrag": { + "description": "Detect and optionally mitigate CVE-2026-43284 (DirtyFrag) and CVE-2026-43500 in the Linux kernel.", + "tags": ["security", "inventory", "detection", "mitigation"], + "subdirectory": "security/dirtyfrag", + "steps": [ + "copy dirtyfrag.cf services/cfbs/modules/dirtyfrag/dirtyfrag.cf", + "copy patched-kernels.json services/cfbs/modules/dirtyfrag/patched-kernels.json", + "policy_files services/cfbs/modules/dirtyfrag/dirtyfrag.cf", + "bundles dirtyfrag:main", + "input ./input.json def.json" + ], + "input": [ + { + "type": "string", + "variable": "mitigate_esp", + "namespace": "dirtyfrag", + "bundle": "main", + "label": "Mitigate CVE-2026-43284 (ESP/IPComp)", + "question": "Blacklist esp4, esp6, ipcomp4, ipcomp6 kernel modules? (breaks IPsec) [true/false]", + "default": "false" + }, + { + "type": "string", + "variable": "mitigate_rxrpc", + "namespace": "dirtyfrag", + "bundle": "main", + "label": "Mitigate CVE-2026-43500 (RxRPC)", + "question": "Blacklist rxrpc kernel module? (breaks AFS/RxRPC) [true/false]", + "default": "false" + }, + { + "type": "string", + "variable": "mitigate_userns", + "namespace": "dirtyfrag", + "bundle": "main", + "label": "Mitigate CVE-2026-43284 via user namespaces", + "question": "Set user.max_user_namespaces=0? (blocks ESP exploit without disabling IPsec, may break rootless containers) [true/false]", + "default": "false" + } + ] + }, "demo": { "description": "Enables convenient and insecure settings for demoing CFEngine.", "subdirectory": "management/demo", diff --git a/security/dirtyfrag/README.md b/security/dirtyfrag/README.md new file mode 100644 index 0000000..8d4b3d6 --- /dev/null +++ b/security/dirtyfrag/README.md @@ -0,0 +1,138 @@ +Dirty Frag is a pair of kernel page-cache write vulnerabilities affecting Linux kernel modules that use nonlinear sk_buff (skb) fragments. An unprivileged local attacker with access to a network namespace can trigger out-of-bounds memory writes, potentially leading to privilege escalation. + +- **CVE-2026-43284** (xfrm-ESP/IPComp): Affects `esp4.ko`, `esp6.ko`, `ipcomp.ko`, and `ipcomp6.ko` modules when unprivileged user namespaces are enabled. Patched in stable kernel trees as of May 2026. +- **CVE-2026-43500** (RxRPC): Affects `rxrpc.ko` module. Patches available for some distros as of May 2026; mitigation via module blacklisting where unpatched. + +## Vulnerability conditions + +- **CVE-2026-43284**: Requires `esp4`, `esp6`, `ipcomp`, or `ipcomp6` kernel modules present AND `/proc/sys/kernel/unprivileged_userns_clone` set to `1` +- **CVE-2026-43500**: Requires `rxrpc` kernel module present (no additional prerequisites) + +## Inventory + +After adding this module you can view Dirty Frag vulnerability status in Mission Portal Inventory Report: + +[![Inventory showing Dirty Frag status](https://raw.githubusercontent.com/cfengine/modules/master/security/dirtyfrag/inventory-status.png)](https://raw.githubusercontent.com/cfengine/modules/master/security/dirtyfrag/inventory-status.png) + +- **Dirty Frag CVE-2026-43284 (xfrm-ESP) status**: + - `VULNERABLE (esp4, esp6 loaded)` -- vulnerable modules currently in memory (names vary by host) + - `VULNERABLE (modules on disk, none loaded)` -- modules present but not loaded; latent risk + - `PATCHED (kernel fix applied)` -- running kernel version includes the fix (auto-detected or admin-declared) + - `MITIGATED (blacklist in place)` -- modprobe blacklist or userns restriction active + - `NOT AFFECTED` -- vulnerable modules not present on this host +- **Dirty Frag CVE-2026-43500 (RxRPC) status**: + - `VULNERABLE (rxrpc loaded)` -- module currently in memory + - `VULNERABLE (module on disk, not loaded)` -- module present but not loaded; latent risk + - `PATCHED (kernel fix applied)` -- running kernel version includes the fix (auto-detected or admin-declared) + - `MITIGATED (blacklist in place)` -- modprobe blacklist active + - `NOT AFFECTED` -- rxrpc module not present on this host + +## Mitigation + +Each CVE has an independent toggle and separate conf file: + +**CVE-2026-43284** (ESP/IPComp) -- `/etc/modprobe.d/dirtyfrag-esp.conf`: + +``` +# Dirty Frag CVE-2026-43284 mitigation: block xfrm-ESP and IPComp +install esp4 /bin/false +install esp6 /bin/false +install ipcomp4 /bin/false +install ipcomp6 /bin/false +``` + +**CVE-2026-43500** (RxRPC) -- `/etc/modprobe.d/dirtyfrag-rxrpc.conf`: + +``` +# Dirty Frag CVE-2026-43500 mitigation: block RxRPC +install rxrpc /bin/false +``` + +This prevents the vulnerable modules from loading. When mitigation is first applied, already-loaded modules are unloaded via `rmmod`. + +**CVE-2026-43284 alternative** (user namespaces) -- `/etc/sysctl.d/dirtyfrag-userns.conf`: + +``` +# Dirty Frag CVE-2026-43284 mitigation: disable unprivileged user namespaces +# Blocks ESP/IPComp exploit without disabling IPsec. +# WARNING: May affect rootless containers and sandboxed applications. +user.max_user_namespaces = 0 +``` + +This blocks the ESP/IPComp exploit path without blacklisting the modules, preserving IPsec functionality. Use this instead of `mitigate_esp` on hosts that require IPsec. Note: this does **not** mitigate CVE-2026-43500 (RxRPC) and may break rootless containers (Podman, Docker rootless), Flatpak, and browser sandboxes. Applied via `sysctl --system` on first write. + +All mitigations are **disabled by default** -- the module only reports status unless the corresponding CMDB variable is set to `"true"`. + +## Usage + +Add the policy to your inputs: + +``` +inputs "security/dirtyfrag/dirtyfrag.cf" +``` + +To enable mitigation, set one or both variables in your site's `def.json` (Augments): + +```json +{ + "variables": { + "dirtyfrag:main.mitigate_esp": { "value": "true" }, + "dirtyfrag:main.mitigate_rxrpc": { "value": "true" }, + "dirtyfrag:main.mitigate_userns": { "value": "true" }, + "dirtyfrag:main.esp_patched": { "value": "true" }, + "dirtyfrag:main.rxrpc_patched": { "value": "true" } + } +} +``` + +| Variable | What it does | Trade-off | +|----------|-------------|-----------| +| `mitigate_esp` | Blacklists esp4, esp6, ipcomp4, ipcomp6 | Breaks IPsec | +| `mitigate_rxrpc` | Blacklists rxrpc | Breaks AFS/RxRPC | +| `mitigate_userns` | Sets `user.max_user_namespaces=0` | May break rootless containers/sandboxes | +| `esp_patched` | Declare CVE-2026-43284 as patched | Admin must verify kernel is actually patched | +| `rxrpc_patched` | Declare CVE-2026-43500 as patched | Admin must verify kernel is actually patched | + +Typical combinations: +- **Most hosts**: `mitigate_esp` + `mitigate_rxrpc` (full protection) +- **IPsec hosts**: `mitigate_userns` + `mitigate_rxrpc` (preserves IPsec) +- **Container hosts needing IPsec**: `mitigate_rxrpc` only (partial, accept ESP risk until patched kernel) + +Default behavior (variables unset) is status-only reporting. + +## Detection details + +The module checks for vulnerable modules in three ways: + +1. **On-disk `.ko` files** under `/lib/modules/$(kernel_version)/` +2. **Compressed variants** (`.ko.zst`, `.ko.xz`) on distros that compress modules +3. **Currently loaded modules** via `/sys/module/` entries + +For CVE-2026-43284, the module also checks whether unprivileged user namespaces are enabled (`/proc/sys/kernel/unprivileged_userns_clone`), since the exploit requires namespace access. + +## Kernel patch detection + +The module automatically detects whether the running kernel includes fixes for the Dirty Frag CVEs by comparing the kernel version (`uname -r`) against known-patched versions from distro security advisories. This data is maintained in `patched-kernels.json`, shipped alongside the policy. + +Currently tracked distros: + +| Distro | CVE-2026-43284 | CVE-2026-43500 | +|--------|---------------|---------------| +| RHEL/CentOS/Alma/Rocky 8 | 4.18.0-553.123.2 | 4.18.0-553.123.2 | +| RHEL/CentOS/Alma/Rocky 9 | 5.14.0-611.54.1 | 5.14.0-611.54.3 | +| RHEL/CentOS/Alma/Rocky 10 | 6.12.0-124.55.2 | 6.12.0-124.55.3 | +| Debian 11 (Bullseye) | 5.10.251-4 | 5.10.251-4 | +| Debian 12 (Bookworm) | 6.1.170-3 | 6.1.170-3 | +| Debian 13 (Trixie) | 6.12.86-1 | 6.12.86-1 | +| SLES 15 SP7 | 6.4.0-150700.53.45.1 | 6.4.0-150700.53.45.1 | + +When a patched kernel is detected, the status reports `PATCHED (kernel fix applied)` instead of `VULNERABLE`. The module uses `sort -V` (version sort from coreutils) to compare kernel versions. + +For distros not in the data file, or hosts running custom/backported kernels, set the admin override variables `esp_patched` and/or `rxrpc_patched` to `"true"` via augments. + +To update the patched kernel data, edit `patched-kernels.json` and redeploy. The data file is intentionally separate from the policy so it can be updated independently. + +## Adding exceptions + +To exclude specific hosts from mitigation, use conditional augments to override them to a value other than `"true"`. + diff --git a/security/dirtyfrag/dirtyfrag.cf b/security/dirtyfrag/dirtyfrag.cf new file mode 100644 index 0000000..4795ca9 --- /dev/null +++ b/security/dirtyfrag/dirtyfrag.cf @@ -0,0 +1,402 @@ +body file control +{ + namespace => "dirtyfrag"; +} + +bundle agent kernel_patch_check +# @brief Checks whether the running kernel includes fixes for Dirty Frag CVEs +# by comparing the kernel package version against known-patched versions +# from distro security advisories. +# +# Sets classes: +# dirtyfrag:_esp_kernel_patched +# dirtyfrag:_rxrpc_kernel_patched +# dirtyfrag:_patch_data_matched +{ + vars: + "_data_file" + string => "$(this.promise_dirname)/patched-kernels.json"; + + "_data" + data => readjson("${_data_file}"), + if => fileexists("${_data_file}"); + + "_entries_idx" + slist => getindices("_data[entries]"), + if => isvariable("_data[entries]"); + + "_os_id" + string => "$(default:sys.os_release[ID])", + if => isvariable("default:sys.os_release[ID]"); + + "_os_ver" + string => "$(default:sys.os_release[VERSION_ID])", + if => isvariable("default:sys.os_release[VERSION_ID]"); + + # Find matching entry: the entry whose id_match and version_match + # both match this host's os-release ID and VERSION_ID. + "_matched_idx" + string => "${_entries_idx}", + if => and( + regcmp("${_data[entries][${_entries_idx}][id_match]}", "${_os_id}"), + regcmp("${_data[entries][${_entries_idx}][version_match]}", "${_os_ver}") + ); + + "_esp_patched_ver" + string => "${_data[entries][${_matched_idx}][cve_2026_43284]}", + if => isvariable("_data[entries][${_matched_idx}][cve_2026_43284]"); + + "_rxrpc_patched_ver" + string => "${_data[entries][${_matched_idx}][cve_2026_43500]}", + if => isvariable("_data[entries][${_matched_idx}][cve_2026_43500]"); + + classes: + "_patch_data_matched" + expression => isvariable("_matched_idx"); + + # Use sort -V to check: if the patched version sorts <= running version, + # then the running kernel is patched. We test by checking that the + # patched version comes first (or equal) in version-sorted order. + # printf '%s\n' "$patched" "$running" | sort -V | head -1 + # If result == patched, then running >= patched. + "_esp_kernel_patched" + expression => returnszero( + "/usr/bin/test \"$(const.dollar)(/usr/bin/printf '%s\n' '${_esp_patched_ver}' '$(default:sys.release)' | /usr/bin/sort -V | /usr/bin/head -1)\" = '${_esp_patched_ver}'", + "useshell" + ), + if => isvariable("_esp_patched_ver"); + + "_rxrpc_kernel_patched" + expression => returnszero( + "/usr/bin/test \"$(const.dollar)(/usr/bin/printf '%s\n' '${_rxrpc_patched_ver}' '$(default:sys.release)' | /usr/bin/sort -V | /usr/bin/head -1)\" = '${_rxrpc_patched_ver}'", + "useshell" + ), + if => isvariable("_rxrpc_patched_ver"); + + reports: + inform_mode._patch_data_matched:: + "Dirty Frag: matched distro ${_os_id} ${_os_ver} (entry ${_matched_idx})"; + + inform_mode._esp_kernel_patched:: + "Dirty Frag CVE-2026-43284: kernel $(default:sys.release) >= ${_esp_patched_ver} (PATCHED)"; + + inform_mode._rxrpc_kernel_patched:: + "Dirty Frag CVE-2026-43500: kernel $(default:sys.release) >= ${_rxrpc_patched_ver} (PATCHED)"; +} + +bundle agent main +# @brief Detects Dirty Frag (CVE-2026-43284, CVE-2026-43500) vulnerability +# and applies CMDB-toggleable mitigations via module blacklisting. +# +# Usage: +# inputs "security/dirtyfrag/dirtyfrag.cf" +# +# CMDB variables (set via def.json augments): +# { +# "variables": { +# "dirtyfrag:main.mitigate_esp": { "value": "true" }, +# "dirtyfrag:main.mitigate_rxrpc": { "value": "true" }, +# "dirtyfrag:main.mitigate_userns": { "value": "true" }, +# "dirtyfrag:main.esp_patched": { "value": "true" }, +# "dirtyfrag:main.rxrpc_patched": { "value": "true" } +# } +# } +# +# Mitigation toggles (each independently controls a mitigation strategy): +# mitigate_esp -> blacklists esp4, esp6, ipcomp4, ipcomp6 +# mitigate_rxrpc -> blacklists rxrpc +# mitigate_userns -> sets user.max_user_namespaces=0 via sysctl +# (blocks CVE-2026-43284 without disabling IPsec, +# but may affect rootless containers/sandboxes; +# does NOT mitigate CVE-2026-43500) +# +# Admin patch overrides (suppress false positives on patched kernels): +# esp_patched -> declare CVE-2026-43284 as patched on this host +# rxrpc_patched -> declare CVE-2026-43500 as patched on this host +# +# Kernel patch detection is automatic for known distro versions +# (see patched-kernels.json). The admin overrides are for distros +# not yet in the data file, or custom/backported kernels. +# +# When disabled (default), the module only reports vulnerability status. +{ + methods: + # Run kernel patch check before evaluating status + "kernel_patch_check" usebundle => "dirtyfrag:kernel_patch_check"; + + vars: + # --- Constants --- + "_esp_conf_path" string => "/etc/modprobe.d/dirtyfrag-esp.conf"; + "_rxrpc_conf_path" string => "/etc/modprobe.d/dirtyfrag-rxrpc.conf"; + + "_esp_conf_content" + string => concat( + "# Dirty Frag CVE-2026-43284 mitigation: block xfrm-ESP and IPComp$(const.n)", + "install esp4 /bin/false$(const.n)", + "install esp6 /bin/false$(const.n)", + "install ipcomp4 /bin/false$(const.n)", + "install ipcomp6 /bin/false$(const.n)" + ); + + "_rxrpc_conf_content" + string => concat( + "# Dirty Frag CVE-2026-43500 mitigation: block RxRPC$(const.n)", + "install rxrpc /bin/false$(const.n)" + ); + + "_userns_conf_path" string => "/etc/sysctl.d/dirtyfrag-userns.conf"; + + "_userns_conf_content" + string => concat( + "# Dirty Frag CVE-2026-43284 mitigation: disable unprivileged user namespaces$(const.n)", + "# Blocks ESP/IPComp exploit without disabling IPsec.$(const.n)", + "# WARNING: May affect rootless containers and sandboxed applications.$(const.n)", + "user.max_user_namespaces = 0$(const.n)" + ); + + # --- Read kernel version --- + "_kver" string => "$(default:sys.release)"; + + # --- Module paths --- + "_esp4_path" string => "/lib/modules/$(_kver)/kernel/net/ipv4/esp4.ko"; + "_esp6_path" string => "/lib/modules/$(_kver)/kernel/net/ipv6/esp6.ko"; + "_ipcomp4_path" string => "/lib/modules/$(_kver)/kernel/net/ipv4/ipcomp.ko"; + + "_ipcomp6_path" + string => "/lib/modules/$(_kver)/kernel/net/ipv6/ipcomp6.ko"; + + "_rxrpc_path" string => "/lib/modules/$(_kver)/kernel/net/rxrpc/rxrpc.ko"; + "_ns_proc" string => "/proc/sys/kernel/unprivileged_userns_clone"; + + # --- Read the unprivileged user namespace setting --- + "_ns_val" + string => readfile("${_ns_proc}"), + if => fileexists("${_ns_proc}"); + + # --- Loaded-module detail for inventory --- + "_esp_loaded_csv" + string => format( + "%s%s%s%s", + ifelse("_esp4_loaded", "esp4, ", ""), + ifelse("_esp6_loaded", "esp6, ", ""), + ifelse("_ipcomp4_loaded", "ipcomp, ", ""), + ifelse("_ipcomp6_loaded", "ipcomp6, ", "") + ); + + # Trim trailing ", " + "_esp_loaded_names" + string => regex_replace("${_esp_loaded_csv}", ",\s*$", "", ""); + + # --- Status strings --- + "_esp_status" + string => ifelse( + "dirtyfrag_esp_needs_mitigation._esp_any_loaded", + "VULNERABLE (${_esp_loaded_names} loaded)", + "dirtyfrag_esp_needs_mitigation", + "VULNERABLE (modules on disk, none loaded)", + "dirtyfrag:kernel_patch_check._esp_kernel_patched|_esp_admin_patched", + "PATCHED (kernel fix applied)", + "dirtyfrag_esp_present._esp_mitigated", + "MITIGATED (blacklist in place)", + "NOT AFFECTED" + ); + + "_rxrpc_status" + string => ifelse( + "dirtyfrag_rxrpc_needs_mitigation._rxrpc_loaded", + "VULNERABLE (rxrpc loaded)", + "dirtyfrag_rxrpc_needs_mitigation", + "VULNERABLE (module on disk, not loaded)", + "dirtyfrag:kernel_patch_check._rxrpc_kernel_patched|_rxrpc_admin_patched", + "PATCHED (kernel fix applied)", + "dirtyfrag_rxrpc_present._rxrpc_mitigated", + "MITIGATED (blacklist in place)", + "NOT AFFECTED" + ); + + # --- Inventory output for Mission Portal --- + "inventory_dirtyfrag_esp" + string => "CVE-2026-43284 (xfrm-ESP): $(_esp_status)", + meta => { + "inventory", + "attribute_name=Dirty Frag CVE-2026-43284 (xfrm-ESP) status", + }, + comment => "CVE-2026-43284 xfrm-ESP mitigation status"; + + "inventory_dirtyfrag_rxrpc" + string => "CVE-2026-43500 (RxRPC): $(_rxrpc_status)", + meta => { + "inventory", + "attribute_name=Dirty Frag CVE-2026-43500 (RxRPC) status", + }, + comment => "CVE-2026-43500 RxRPC mitigation status"; + + classes: + # --- CMDB toggles --- + "_mitigate_esp" expression => strcmp("true", "$(mitigate_esp)"); + "_mitigate_rxrpc" expression => strcmp("true", "$(mitigate_rxrpc)"); + "_mitigate_userns" expression => strcmp("true", "$(mitigate_userns)"); + + # --- Admin override: manually declare host as patched --- + "_esp_admin_patched" expression => strcmp("true", "$(esp_patched)"); + "_rxrpc_admin_patched" expression => strcmp("true", "$(rxrpc_patched)"); + + # --- Unprivileged user namespace enabled? --- + "_ns_proc_file_exists" expression => fileexists("${_ns_proc}"); + "_ns_val_is_1" expression => strcmp("${_ns_val}", "1"); + "_userns_enabled" and => { "_ns_proc_file_exists", "_ns_val_is_1" }; + + # --- xfrm-ESP/IPComp modules present? --- + "_esp4_on_disk" expression => fileexists("${_esp4_path}"); + "_esp6_on_disk" expression => fileexists("${_esp6_path}"); + "_ipcomp4_on_disk" expression => fileexists("${_ipcomp4_path}"); + "_ipcomp6_on_disk" expression => fileexists("${_ipcomp6_path}"); + + # Compressed variants (.ko.zst, .ko.xz) + "_esp4_on_disk_z" expression => fileexists("${_esp4_path}.zst"); + "_esp6_on_disk_z" expression => fileexists("${_esp6_path}.zst"); + "_ipcomp4_on_disk_z" expression => fileexists("${_ipcomp4_path}.zst"); + "_ipcomp6_on_disk_z" expression => fileexists("${_ipcomp6_path}.zst"); + "_esp4_on_disk_xz" expression => fileexists("${_esp4_path}.xz"); + "_esp6_on_disk_xz" expression => fileexists("${_esp6_path}.xz"); + "_ipcomp4_on_disk_xz" expression => fileexists("${_ipcomp4_path}.xz"); + "_ipcomp6_on_disk_xz" expression => fileexists("${_ipcomp6_path}.xz"); + + # Currently loaded + "_esp4_loaded" expression => isdir("/sys/module/esp4"); + "_esp6_loaded" expression => isdir("/sys/module/esp6"); + "_ipcomp4_loaded" expression => isdir("/sys/module/ipcomp"); + "_ipcomp6_loaded" expression => isdir("/sys/module/ipcomp6"); + + "_esp_any_loaded" + or => { + "_esp4_loaded", "_esp6_loaded", "_ipcomp4_loaded", "_ipcomp6_loaded" + }; + + "dirtyfrag_esp_present" + or => { + "_esp4_on_disk", + "_esp6_on_disk", + "_ipcomp4_on_disk", + "_ipcomp6_on_disk", + "_esp4_on_disk_z", + "_esp6_on_disk_z", + "_ipcomp4_on_disk_z", + "_ipcomp6_on_disk_z", + "_esp4_on_disk_xz", + "_esp6_on_disk_xz", + "_ipcomp4_on_disk_xz", + "_ipcomp6_on_disk_xz", + "_esp4_loaded", + "_esp6_loaded", + "_ipcomp4_loaded", + "_ipcomp6_loaded", + }; + + # --- RxRPC module present? --- + "_rxrpc_on_disk" expression => fileexists("${_rxrpc_path}"); + "_rxrpc_on_disk_z" expression => fileexists("${_rxrpc_path}.zst"); + "_rxrpc_on_disk_xz" expression => fileexists("${_rxrpc_path}.xz"); + "_rxrpc_loaded" expression => isdir("/sys/module/rxrpc"); + + "dirtyfrag_rxrpc_present" + or => { + "_rxrpc_on_disk", + "_rxrpc_on_disk_z", + "_rxrpc_on_disk_xz", + "_rxrpc_loaded", + }; + + # --- Mitigation conf files in place? --- + "_esp_conf_exists" expression => fileexists("${_esp_conf_path}"); + "_rxrpc_conf_exists" expression => fileexists("${_rxrpc_conf_path}"); + "_userns_conf_exists" expression => fileexists("${_userns_conf_path}"); + + # ESP is mitigated by modprobe blacklist, disabled userns, patched kernel, + # or admin override + "_esp_mitigated" + or => { + "_esp_conf_exists", + "_userns_conf_exists", + "!_userns_enabled", + "dirtyfrag:kernel_patch_check._esp_kernel_patched", + "_esp_admin_patched", + }; + + # RxRPC is mitigated by the modprobe blacklist, patched kernel, + # or admin override + "_rxrpc_mitigated" + or => { + "_rxrpc_conf_exists", + "dirtyfrag:kernel_patch_check._rxrpc_kernel_patched", + "_rxrpc_admin_patched", + }; + + # --- Per-CVE vulnerability checks --- + "dirtyfrag_esp_needs_mitigation" + and => { "dirtyfrag_esp_present", "!_esp_mitigated" }; + + "dirtyfrag_rxrpc_needs_mitigation" + and => { "dirtyfrag_rxrpc_present", "!_rxrpc_mitigated" }; + + files: + # --- CVE-2026-43284: ESP/IPComp mitigation --- + _mitigate_esp:: + "${_esp_conf_path}" + create => "true", + content => "${_esp_conf_content}", + classes => default:results("bundle", "dirtyfrag_esp_conf"); + + # --- CVE-2026-43500: RxRPC mitigation --- + _mitigate_rxrpc:: + "${_rxrpc_conf_path}" + create => "true", + content => "${_rxrpc_conf_content}", + classes => default:results("bundle", "dirtyfrag_rxrpc_conf"); + + # --- CVE-2026-43284 alternative: disable unprivileged user namespaces --- + _mitigate_userns:: + "${_userns_conf_path}" + create => "true", + content => "${_userns_conf_content}", + classes => default:results("bundle", "dirtyfrag_userns_conf"); + + commands: + # --- Unload ESP/IPComp modules after conf written --- + _mitigate_esp.dirtyfrag_esp_conf_repaired:: + "/sbin/rmmod" + arglist => { "esp4", "esp6", "ipcomp", "ipcomp6" }, + comment => "Unload ESP/IPComp modules already in memory"; + + # --- Unload RxRPC module after conf written --- + _mitigate_rxrpc.dirtyfrag_rxrpc_conf_repaired:: + "/sbin/rmmod" + arglist => { "rxrpc" }, + comment => "Unload RxRPC module already in memory"; + + # --- Apply sysctl after writing userns conf --- + _mitigate_userns.dirtyfrag_userns_conf_repaired:: + "/sbin/sysctl" + arglist => { "--system" }, + comment => "Apply user.max_user_namespaces=0 without reboot"; + + reports: + inform_mode:: + + "Dirty Frag CVE-2026-43284 (xfrm-ESP/IPComp): $(_esp_status)" + if => "dirtyfrag_esp_present"; + + "Dirty Frag CVE-2026-43500 (RxRPC): $(_rxrpc_status)" + if => "dirtyfrag_rxrpc_present"; +} + +body file control +{ + namespace => "default"; +} + +bundle agent __main__ +{ + methods: + "dirtyfrag:main"; +} diff --git a/security/dirtyfrag/inventory-status.png b/security/dirtyfrag/inventory-status.png new file mode 100644 index 0000000..4adcd0b Binary files /dev/null and b/security/dirtyfrag/inventory-status.png differ diff --git a/security/dirtyfrag/patched-kernels.json b/security/dirtyfrag/patched-kernels.json new file mode 100644 index 0000000..b4dab09 --- /dev/null +++ b/security/dirtyfrag/patched-kernels.json @@ -0,0 +1,66 @@ +{ + "_meta": { + "description": "Minimum patched kernel package versions for Dirty Frag CVEs. Keyed by distro match (os_release ID + major version). The policy matches the running host against these entries and uses sort -V to compare the installed kernel package version against the minimum patched version.", + "updated": "2026-05-12", + "sources": [ + "https://access.redhat.com/security/vulnerabilities/RHSB-2026-003", + "https://security-tracker.debian.org/tracker/CVE-2026-43284", + "https://security-tracker.debian.org/tracker/CVE-2026-43500", + "https://ubuntu.com/security/CVE-2026-43500", + "https://almalinux.org/blog/2026-05-07-dirty-frag/", + "https://www.suse.com/security/cve/CVE-2026-43284.html", + "https://explore.alas.aws.amazon.com/CVE-2026-43284.html" + ] + }, + "entries": [ + { + "label": "RHEL/CentOS/Alma/Rocky/OL 8", + "id_match": "^(rhel|centos|rocky|almalinux|ol)$", + "version_match": "^8", + "cve_2026_43284": "4.18.0-553.123.2", + "cve_2026_43500": "4.18.0-553.123.2" + }, + { + "label": "RHEL/CentOS/Alma/Rocky/OL 9", + "id_match": "^(rhel|centos|rocky|almalinux|ol)$", + "version_match": "^9", + "cve_2026_43284": "5.14.0-611.54.1", + "cve_2026_43500": "5.14.0-611.54.3" + }, + { + "label": "RHEL/CentOS/Alma/Rocky/OL 10", + "id_match": "^(rhel|centos|rocky|almalinux|ol)$", + "version_match": "^10", + "cve_2026_43284": "6.12.0-124.55.2", + "cve_2026_43500": "6.12.0-124.55.3" + }, + { + "label": "Debian 11 (Bullseye)", + "id_match": "^debian$", + "version_match": "^11", + "cve_2026_43284": "5.10.251-4", + "cve_2026_43500": "5.10.251-4" + }, + { + "label": "Debian 12 (Bookworm)", + "id_match": "^debian$", + "version_match": "^12", + "cve_2026_43284": "6.1.170-3", + "cve_2026_43500": "6.1.170-3" + }, + { + "label": "Debian 13 (Trixie)", + "id_match": "^debian$", + "version_match": "^13", + "cve_2026_43284": "6.12.86-1", + "cve_2026_43500": "6.12.86-1" + }, + { + "label": "SLES 15 SP7", + "id_match": "^sles$", + "version_match": "^15\\.7", + "cve_2026_43284": "6.4.0-150700.53.45.1", + "cve_2026_43500": "6.4.0-150700.53.45.1" + } + ] +}