Skip to content

Conversation

@BulaYoungR
Copy link

@BulaYoungR BulaYoungR commented Dec 4, 2025

When running migration tests with shared TPM, the VM fails to start with "cannot execute binary /usr/bin/swtpm: Permission denied" error. This occurs because SELinux context for swtpm binary is incorrect or the required SELinux policies are not properly configured.

Changes:

  • Add prepare_swtpm_selinux() function to automatically configure SELinux environment for swtpm on both local and remote hosts
  • Install swtpm-selinux package if missing
  • Restore SELinux contexts for swtpm binaries
  • Enable required SELinux booleans (swtpm_use_tpm_device, virt_use_swtpm)
  • Fix typo in check_tpm_security_context(): 'remote' -> 'remote_host'

Committer: Bolatbek Issakh bissakh@redhat.com

Summary by CodeRabbit

  • Tests
    • Enhanced test infrastructure for virtual TPM migration scenarios with improved SELinux context preparation on both local and remote hosts during storage setup processes.

✏️ Tip: You can customize this high-level summary in your review settings.

When running migration tests with shared TPM, the VM fails to start with
"cannot execute binary /usr/bin/swtpm: Permission denied" error. This
occurs because SELinux context for swtpm binary is incorrect or the
required SELinux policies are not properly configured.

Changes:
- Add prepare_swtpm_selinux() function to automatically configure
  SELinux environment for swtpm on both local and remote hosts
- Install swtpm-selinux package if missing
- Restore SELinux contexts for swtpm binaries
- Enable required SELinux booleans (swtpm_use_tpm_device, virt_use_swtpm)
- Fix typo in check_tpm_security_context(): 'remote' -> 'remote_host'

Committer: Bolatbek Issakh <bissakh@redhat.com>
@coderabbitai
Copy link

coderabbitai bot commented Dec 4, 2025

Walkthrough

This change introduces a new helper function prepare_swtpm_selinux() that prepares SELinux context for swtpm on both local and remote hosts by installing the swtpm-selinux package, applying file context restoration, and toggling relevant SELinux booleans. The helper is integrated into the NFS and Ceph setup paths, with execution occurring on the local host first, followed by remote host execution via SSH sessions. Related logging and execution paths were adjusted to consistently use remote execution when a session is provided.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • New helper function logic: The prepare_swtpm_selinux() function contains package installation, file context restoration, and SELinux boolean toggling that requires careful verification of command correctness and error handling.
  • Integration points: The function is called in both setup_nfs() and setup_ceph() setup paths with different session contexts (local vs remote), requiring verification that both paths are correctly implemented and the session lifecycle is properly managed.
  • Remote execution consistency: Changes to use remote execution paths conditionally based on session parameter need review to ensure remote and local execution branches behave correctly.
  • Session management: Verify that SSH session cleanup (server_session closure) is properly placed and doesn't introduce connection issues or resource leaks.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title directly and specifically describes the main change: fixing SELinux permission denied errors for swtpm in migration tests by configuring SELinux contexts.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

@BulaYoungR
Copy link
Author

Before Fix

2025-12-04 14:45:57,434 avocado.app human            L0129 DEBUG|  (1/1) type_specific.io-github-autotest-libvirt.migration_with_vtpm.migration_with_shared_tpm.nfs.persistent_and_p2p:
2025-12-04 14:45:57,434 avocado.app human            L0136 DEBUG| ERROR: VM 'avocado-vt-vm1' failed to start: error: Failed to start domain 'avocado-vt-vm1'\nerror: operation failed: swtpm died and reported: 2025-12-04 19:45:24.679+0000: 110206: debug : virExec:890 : Setting child security label to system_u:system_r:svirt_t:s0:... (122.38 s)
2025-12-04 14:45:57,435 avocado.job testlogs         L0138 INFO | type_specific.io-github-autotest-libvirt.migration_with_vtpm.migration_with_shared_tpm.nfs.persistent_and_p2p: ERROR
2025-12-04 14:45:57,435 avocado.job testlogs         L0139 INFO | More information in /var/log/avocado/job-results/job-2025-12-04T14.43-e8d2d27/test-results/1-type_specific.io-github-autotest-libvirt.migration_with_vtpm.migration_with_shared_tpm.nfs.persistent_and_p2p
2025-12-04 14:45:57,490 avocado.core.task.statemachine statemachine     L0146 DEBUG| Task "1-type_specific.io-github-autotest-libvirt.migration_with_vtpm.migration_with_shared_tpm.nfs.persistent_and_p2p" finished with status: RuntimeTaskStatus.FINISHED
2025-12-04 14:45:57,541 avocado.job job              L0659 INFO | Test results available in /var/log/avocado/job-results/job-2025-12-04T14.43-e8d2d27
2025-12-04 14:45:57,541 avocado.app human            L0146 INFO | RESULTS    : PASS 0 | ERROR 1 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 | CANCEL 0

After Fix

JOB ID     : 262fc8643d6786d2bf311c50f3b3edf43d048d22
JOB LOG    : /var/log/avocado/job-results/job-2025-12-04T15.25-262fc86/job.log
 (1/1) type_specific.io-github-autotest-libvirt.migration_with_vtpm.migration_with_shared_tpm.nfs.persistent_and_p2p: STARTED
 (1/1) type_specific.io-github-autotest-libvirt.migration_with_vtpm.migration_with_shared_tpm.nfs.persistent_and_p2p: PASS (249.23 s)
RESULTS    : PASS 1 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 | CANCEL 0
JOB HTML   : /var/log/avocado/job-results/job-2025-12-04T15.25-262fc86/results.html
JOB TIME   : 250.66 s

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f5f4654 and 20a2536.

📒 Files selected for processing (1)
  • libvirt/tests/src/migration/migration_with_vtpm/migration_with_shared_tpm.py (4 hunks)
🧰 Additional context used
🪛 Ruff (0.14.7)
libvirt/tests/src/migration/migration_with_vtpm/migration_with_shared_tpm.py

19-19: Unused function argument: params

(ARG001)


47-47: Function call with shell=True parameter identified, security issue

(S604)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Python 3.11
  • GitHub Check: Python 3.12
  • GitHub Check: Python 3.9
  • GitHub Check: Python 3.8
🔇 Additional comments (3)
libvirt/tests/src/migration/migration_with_vtpm/migration_with_shared_tpm.py (3)

222-236: LGTM! SELinux preparation properly integrated.

The SELinux preparation is correctly called on both local and remote hosts before the mount operations, and the session lifecycle is properly managed.


258-275: Verify restorecon consistency after mount operations.

After calling prepare_swtpm_selinux on both hosts and mounting on the remote, line 274 runs restorecon -Rv /var/lib/libvirt/swtpm only on the local host. Consider whether:

  1. This restorecon is still necessary after the prepare_swtpm_selinux call, or
  2. The same restorecon should also be applied on the remote host after its mount operation (line 273).

62-62: Good catch fixing the variable name!

Correctly changed the log statement to use remote_host (the actual parameter name) instead of the undefined remote variable.

Comment on lines +19 to +50
def prepare_swtpm_selinux(params, test, session=None):
"""
Prepare SELinux environment for swtpm to work properly.
This fixes "Permission denied" errors when libvirt tries to execute swtpm.
:param params: dict, test parameters
:param test: test object
:param session: remote session object (None for local execution)
"""
test.log.info("Preparing SELinux environment for swtpm%s.",
" on remote host" if session else "")

commands = [
"rpm -q swtpm-selinux || yum install -y swtpm-selinux",
"restorecon -v /usr/bin/swtpm",
"restorecon -v /usr/bin/swtpm_setup",
"restorecon -Rv /var/lib/swtpm-localca 2>/dev/null || true",
"getsebool swtpm_use_tpm_device &>/dev/null && setsebool -P swtpm_use_tpm_device on || true",
"getsebool virt_use_swtpm &>/dev/null && setsebool -P virt_use_swtpm on || true",
]

for cmd in commands:
test.log.debug("Running: %s", cmd)
if session:
status, output = session.cmd_status_output(cmd, timeout=120)
if status and "rpm -q" not in cmd:
test.log.warning("Command '%s' failed on remote: %s", cmd, output)
else:
result = process.run(cmd, ignore_status=True, shell=True, timeout=120)
if result.exit_status and "rpm -q" not in cmd:
test.log.warning("Command '%s' failed: %s", cmd, result.stderr_text)

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Remove unused params parameter.

The params parameter is declared but never used in the function body. Consider removing it to clean up the function signature.

Apply this diff:

-def prepare_swtpm_selinux(params, test, session=None):
+def prepare_swtpm_selinux(test, session=None):
     """
     Prepare SELinux environment for swtpm to work properly.
     This fixes "Permission denied" errors when libvirt tries to execute swtpm.
 
-    :param params: dict, test parameters
     :param test: test object
     :param session: remote session object (None for local execution)
     """

And update the function calls at lines 224, 233, 260, and 271:

-        prepare_swtpm_selinux(params, test)
+        prepare_swtpm_selinux(test)
-        prepare_swtpm_selinux(params, test, session=server_session)
+        prepare_swtpm_selinux(test, session=server_session)

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Ruff (0.14.7)

19-19: Unused function argument: params

(ARG001)


47-47: Function call with shell=True parameter identified, security issue

(S604)

🤖 Prompt for AI Agents
In libvirt/tests/src/migration/migration_with_vtpm/migration_with_shared_tpm.py
around lines 19 to 50 the function prepare_swtpm_selinux(params, test,
session=None) declares an unused params parameter; remove params from the
signature so it becomes prepare_swtpm_selinux(test, session=None) and update all
internal uses accordingly (none needed), then update every call site referenced
in the review at lines 224, 233, 260, and 271 to stop passing the params
argument (call prepare_swtpm_selinux(test, session) or
prepare_swtpm_selinux(test) as appropriate).

" on remote host" if session else "")

commands = [
"rpm -q swtpm-selinux || yum install -y swtpm-selinux",
Copy link
Contributor

Choose a reason for hiding this comment

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

We do not install any package on host, instead we should check if the package is installed. If it does not exist, let's skip the case if this package is required.

"restorecon -v /usr/bin/swtpm",
"restorecon -v /usr/bin/swtpm_setup",
"restorecon -Rv /var/lib/swtpm-localca 2>/dev/null || true",
"getsebool swtpm_use_tpm_device &>/dev/null && setsebool -P swtpm_use_tpm_device on || true",
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we simply run setsebool command?

"getsebool virt_use_swtpm &>/dev/null && setsebool -P virt_use_swtpm on || true",
]

for cmd in commands:
Copy link
Contributor

Choose a reason for hiding this comment

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

To execute a command, you can use utils_misc.cmd_status_output()

from provider.migration import base_steps


def prepare_swtpm_selinux(params, test, session=None):
Copy link
Contributor

Choose a reason for hiding this comment

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

params is no used

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