Skip to content

fix(charts): disable KVM nested virtualization in Talos presets (CVE-2026-53359)#224

Open
Andrei Kvapil (kvaps) wants to merge 2 commits into
mainfrom
security/cve-2026-53359-disable-nested-virt
Open

fix(charts): disable KVM nested virtualization in Talos presets (CVE-2026-53359)#224
Andrei Kvapil (kvaps) wants to merge 2 commits into
mainfrom
security/cve-2026-53359-disable-nested-virt

Conversation

@kvaps

@kvaps Andrei Kvapil (kvaps) commented Jul 7, 2026

Copy link
Copy Markdown
Member

Summary

Disables KVM nested virtualization in the Talos machine config produced by the cozystack and generic presets, to mitigate CVE-2026-53359 ("Januscape"), a guest-to-host escape in the Linux KVM/x86 shadow MMU (a use-after-free in kvm_mmu_get_child_sp() from shadow-page role confusion).

The vulnerable code path is only reachable when a guest is allowed to use nested virtualization; disabling it on the host removes the attack surface regardless of the node kernel patch level. Fixed upstream in 81ccda30b4e8 / stable 6.12.95, 6.6.144, 6.1.177, 6.18.38, 7.1.3 (2026-07-04); no released Talos ships the fixed kernel yet.

Change

Adds kvm_intel.nested=0 and kvm_amd.nested=0 to machine.install.extraKernelArgs in both presets. Both args are set so a single config works on Intel and AMD hosts (the non-matching one is silently ignored).

Notes

  • Presets are embedded assets, so this reaches users through a new tagged talm release (and the downstream cozystack bump that pins talm).
  • Takes effect on the next reboot (kernel module parameter). Remove these args if a workload legitimately needs nested virt and the node kernel is patched.

Part of a coordinated set of PRs (see Related PRs below).

Related PRs

Coordinated CVE-2026-53359 (Januscape) nested-virtualization mitigation across Cozystack repos:

Summary by CodeRabbit

  • Bug Fixes
    • Updated machine configuration to disable KVM nested virtualization on Intel and AMD by injecting required kernel arguments.
    • Added Talos-version-aware handling for UKI boot settings to prevent incompatible configuration output across templates.
  • Tests
    • Added contract tests to verify generated Helm config includes the nested-virtualization mitigation and that full merged configuration passes validation without UKI/argument conflicts.

…2026-53359)

Add kvm_intel.nested=0 and kvm_amd.nested=0 to machine.install.extraKernelArgs in the cozystack and generic presets to mitigate CVE-2026-53359 (Januscape), a KVM guest-to-host escape reachable only when nested virtualization is exposed to the guest. Both args are set so one config covers Intel and AMD hosts.

Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
Assisted-By: Claude <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Helm machine templates now emit nested-virtualization kernel arguments and conditionally disable grubUseUKICmdline for Talos versions where it would conflict. New contract tests cover the rendered templates and full merged config validation.

Changes

Nested virtualization mitigation

Layer / File(s) Summary
Template mitigation
charts/cozystack/templates/_helpers.tpl, charts/generic/templates/_helpers.tpl
Shared Talos machine templates add a CVE-2026-53359 comment, a Talos-version guard for grubUseUKICmdline: false, and extraKernelArgs for kvm_intel.nested=0 and kvm_amd.nested=0.
Contract coverage
pkg/engine/contract_machine_kvmnested_test.go
Contract tests verify the kernel args are rendered, the Talos version gate is applied, and the merged full config validates without the UKI/extraKernelArgs conflict.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GoTest
  participant HelmEngine
  participant ConfigLoader
  participant TalosValidator
  GoTest->>HelmEngine: render template output
  GoTest->>ConfigLoader: load merged machine config
  ConfigLoader->>TalosValidator: validate install config
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: disabling KVM nested virtualization in Talos presets for CVE-2026-53359.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch security/cve-2026-53359-disable-nested-virt

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds extra kernel arguments to disable KVM nested virtualization (kvm_intel.nested=0 and kvm_amd.nested=0) in both cozystack and generic Helm charts to mitigate CVE-2026-53359. The feedback suggests improving flexibility by allowing operators to customize or override these kernel arguments through .Values.extraKernelArgs.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +168 to +171
extraKernelArgs:
# CVE-2026-53359: disable KVM nested virtualization (guest-to-host escape mitigation)
- kvm_intel.nested=0
- kvm_amd.nested=0

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To maintain consistency with other customizable fields (such as extraKernelModules, extraSysctls, etc.) and to allow operators to customize kernel arguments or override this mitigation if needed, consider adding support for an optional extraKernelArgs list in .Values.

    extraKernelArgs:
    # CVE-2026-53359: disable KVM nested virtualization (guest-to-host escape mitigation)
    - kvm_intel.nested=0
    - kvm_amd.nested=0
    {{- with .Values.extraKernelArgs }}
    {{- toYaml . | nindent 4 }}
    {{- end }}

Comment on lines +61 to +64
extraKernelArgs:
# CVE-2026-53359: disable KVM nested virtualization (guest-to-host escape mitigation)
- kvm_intel.nested=0
- kvm_amd.nested=0

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To maintain consistency with other customizable fields (such as extraKernelModules, extraSysctls, etc.) and to allow operators to customize kernel arguments or override this mitigation if needed, consider adding support for an optional extraKernelArgs list in .Values.

    extraKernelArgs:
    # CVE-2026-53359: disable KVM nested virtualization (guest-to-host escape mitigation)
    - kvm_intel.nested=0
    - kvm_amd.nested=0
    {{- with .Values.extraKernelArgs }}
    {{- toYaml . | nindent 4 }}
    {{- end }}

… v1.12+

Talos >1.11 defaults machine.install.grubUseUKICmdline to true (UKI
cmdline) and rejects machine.install.extraKernelArgs alongside it
("install.extraKernelArgs and install.grubUseUKICmdline can't be used
together"). The generated base config carries that default, so the
kvm_intel/kvm_amd nested-virt args on their own rendered a config Talos
refused on apply for every v1.12+ node.

Pin grubUseUKICmdline=false in both presets wherever the base bundle
would set it true (no --talos-version, or >=1.12), so the args land on
the Talos-built kernel command line. The kvm modules are built into the
Talos kernel, so the nested= parameter is settable only via the command
line -- a modprobe.d drop-in or a read-only /sys write cannot set it.

Add contract tests that render the full apply config (base bundle +
preset patch) and run Talos validation, pinning the mitigation and
guarding against the UKI conflict regressing.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
pkg/engine/contract_machine_kvmnested_test.go (1)

105-110: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Restore helmEngine.LookupFunc after the test.

The package-level helmEngine.LookupFunc is reassigned but never restored. Other contract tests in this package share the same global; leaving it mutated risks order-dependent flakiness. Prefer capturing and restoring via t.Cleanup.

♻️ Restore the hook after the test
-	helmEngine.LookupFunc = func(string, string, string) (map[string]any, error) {
-		return map[string]any{}, nil
-	}
+	prevLookup := helmEngine.LookupFunc
+	t.Cleanup(func() { helmEngine.LookupFunc = prevLookup })
+	helmEngine.LookupFunc = func(string, string, string) (map[string]any, error) {
+		return map[string]any{}, nil
+	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/engine/contract_machine_kvmnested_test.go` around lines 105 - 110, The
test mutates the package-level helmEngine.LookupFunc and leaves it changed,
which can affect other contract tests in this package. In
TestContract_Machine_Install_FullConfigValidates_NoUKIConflict, capture the
current LookupFunc before overriding it and restore it with t.Cleanup so the
shared global is returned to its original state after the test finishes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@pkg/engine/contract_machine_kvmnested_test.go`:
- Around line 105-110: The test mutates the package-level helmEngine.LookupFunc
and leaves it changed, which can affect other contract tests in this package. In
TestContract_Machine_Install_FullConfigValidates_NoUKIConflict, capture the
current LookupFunc before overriding it and restore it with t.Cleanup so the
shared global is returned to its original state after the test finishes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 21089072-340b-4bbb-afdc-23b7cea75384

📥 Commits

Reviewing files that changed from the base of the PR and between 6b58604 and 1ff68bd.

📒 Files selected for processing (3)
  • charts/cozystack/templates/_helpers.tpl
  • charts/generic/templates/_helpers.tpl
  • pkg/engine/contract_machine_kvmnested_test.go

@lexfrei

Copy link
Copy Markdown
Contributor

Heads up — I pushed a fix commit (1ff68bd) to this branch. The extraKernelArgs approach as-is produces a config Talos rejects on apply for v1.12+.

Why it failed: talm's apply path serializes the generated base config merged with the preset. On Talos >1.11 the base defaults machine.install.grubUseUKICmdline: true (also when --talos-version is empty — it falls back to the current contract), and Talos validation rejects install.extraKernelArgs alongside it:

install.extraKernelArgs and install.grubUseUKICmdline can't be used together

So the kvm args on their own made every v1.12+ apply fail. Confirmed against a live v1.12.6 node — apply --dry-run shows the base carrying grubUseUKICmdline: true.

The fix: pin grubUseUKICmdline: false in both presets, gated to exactly where the base sets it true (empty --talos-version, or ≥1.12); omitted on explicit <1.12, whose schema predates the field. Added contract tests that render the full apply config and run Talos's own validation, so the conflict can't regress.

Two things worth calling out:

  1. Tradeoff: this switches v1.12+ nodes from the UKI cmdline back to the Talos-built cmdline. Harmless for standard installs, but relevant if anyone relies on UKI/secure-boot cmdline measurement.

  2. Rollout: machine.install.* kernel args are written by the installer, so this takes effect on talm upgrade (installer re-run), not a plain apply --mode=reboot. Verified on a live v1.12.6 node: after apply --mode=reboot the cmdline was unchanged and kvm_intel.nested stayed Y; after upgrade the cmdline gained kvm_intel.nested=0 kvm_amd.nested=0 and nested flipped to N. The "takes effect on the next reboot" line should be corrected, and the coordinated E2E / docs PRs should reflect the upgrade requirement.

kvm_intel/kvm_amd are built into the Talos kernel, so the cmdline is the only way to set nested= — a modprobe.d drop-in or a runtime /sys write can't (the sysfs knob is read-only post-boot).

@kvaps

Copy link
Copy Markdown
Member Author

Thanks Aleksei Sviridkin (@lexfrei) — good catch, and the fix is right. Confirmed the same conflict: extraKernelArgs alone is rejected on Talos ≥1.12 because the base defaults grubUseUKICmdline: true, and even where it isn't rejected it's a no-op under the UKI cmdline. Pinning grubUseUKICmdline: false (gated to where the base sets it true) is the correct fix, and running Talos's own validation in the contract tests is exactly what this needed. The UKI-cmdline → Talos-built-cmdline tradeoff is fine for us — we don't rely on UKI cmdline measurement.

Propagated the same pin to the coordinated PRs, and corrected the rollout wording to "applies on talm upgrade, not apply --reboot" per your live check:

Also confirms your point that kvm_intel/kvm_amd are built into the Talos kernel — so the cmdline is the only lever; the ansible-cozystack PR stays on modprobe.d, since on generic distros those are loadable modules.

One open point: the older docs versions (v0–v1.2) pin Talos v1.10.3, where grubUseUKICmdline doesn't exist yet but UKI is already the default — so extraKernelArgs is a no-op on UEFI there and only Image Factory fixes it. Handling those docs separately.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants