Skip to content

test(jailer): regression test for chroot bind-mount propagation#5939

Open
xxgj wants to merge 1 commit into
firecracker-microvm:mainfrom
xxgj:main
Open

test(jailer): regression test for chroot bind-mount propagation#5939
xxgj wants to merge 1 commit into
firecracker-microvm:mainfrom
xxgj:main

Conversation

@xxgj

@xxgj xxgj commented Jun 7, 2026

Copy link
Copy Markdown

Changes

Bind mounts established on the host inside the chroot before jailer start must propagate into the jailer's mount namespace. The test bind-mounts kernel and rootfs onto empty placeholders in the chroot and drives the API directly (bypassing basic_config to avoid create_jailed_resource hardlinking over the mounts), then asserts a clean SSH boot.

Tests

Successful run

w/ the fix applied

$ sudo ./tools/devtool test -- integration_tests/security/test_jail.py::test_jailer_bind_mount_propagation

...
integration_tests/security/test_jail.py::test_jailer_bind_mount_propagation[PCI_ON-ro-vmlinux-6.1.172] PASSED [ 50%]
integration_tests/security/test_jail.py::test_jailer_bind_mount_propagation[PCI_OFF-ro-vmlinux-6.1.172] PASSED [100%]

--------------------------------- JSON report ----------------------------------
report saved to: ../test_results/test-report.json
============================= slowest 10 durations =============================
1.99s call     integration_tests/security/test_jail.py::test_jailer_bind_mount_propagation[PCI_ON-ro-vmlinux-6.1.172]
1.74s call     integration_tests/security/test_jail.py::test_jailer_bind_mount_propagation[PCI_OFF-ro-vmlinux-6.1.172]
0.01s setup    integration_tests/security/test_jail.py::test_jailer_bind_mount_propagation[PCI_OFF-ro-vmlinux-6.1.172]
0.01s teardown integration_tests/security/test_jail.py::test_jailer_bind_mount_propagation[PCI_OFF-ro-vmlinux-6.1.172]
0.00s setup    integration_tests/security/test_jail.py::test_jailer_bind_mount_propagation[PCI_ON-ro-vmlinux-6.1.172]
0.00s teardown integration_tests/security/test_jail.py::test_jailer_bind_mount_propagation[PCI_ON-ro-vmlinux-6.1.172]
============================== 2 passed in 3.80s ===============================
[Firecracker devtool] Finished test run ...

Reproduce #1089

regression check to confirm the test catches the original bug

Step 1. Revert the fix locally to restore the buggy behavior

diff --git a/src/jailer/src/chroot.rs b/src/jailer/src/chroot.rs
index 56335c03a..488c00436 100644
--- a/src/jailer/src/chroot.rs
+++ b/src/jailer/src/chroot.rs
@@ -32,12 +32,12 @@ pub fn chroot(path: &Path) -> Result<(), JailerError> {
             null(),
             ROOT_DIR.as_ptr(),
             null(),
-            libc::MS_SLAVE | libc::MS_REC,
+            libc::MS_PRIVATE | libc::MS_REC,
             null(),
         )
     })
     .into_empty_result()
-    .map_err(JailerError::MountPropagationSlave)?;
+    .map_err(JailerError::MountPropagationPrivate)?;
 
     // We need a CString for the following mount call.
     let chroot_dir = to_cstring(path)?;
@@ -51,7 +51,7 @@ pub fn chroot(path: &Path) -> Result<(), JailerError> {
             chroot_dir.as_ptr(),
             chroot_dir.as_ptr(),
             null(),
-            libc::MS_BIND | libc::MS_REC,
+            libc::MS_BIND,
             null(),
         )
     })
diff --git a/src/jailer/src/main.rs b/src/jailer/src/main.rs
index 4f87f2563..5951209b7 100644
--- a/src/jailer/src/main.rs
+++ b/src/jailer/src/main.rs
@@ -108,7 +108,7 @@ pub enum JailerError {
     #[error("Failed to bind mount the jail root directory: {0}")]
     MountBind(io::Error),
     #[error("Failed to change the propagation type to slave: {0}")]
-    MountPropagationSlave(io::Error),
+    MountPropagationPrivate(io::Error),
     #[error("{}", format!("{:?} is not a file", .0).replace('\"', ""))]
     NotAFile(PathBuf),
     #[error("{}", format!("{:?} is not a directory", .0).replace('\"', ""))]

Step 2. Run the test

$ sudo ./tools/devtool test -- integration_tests/security/test_jail.py::test_jailer_bind_mount_propagation

...
--------------------------------- JSON report ----------------------------------
report saved to: ../test_results/test-report.json
============================= slowest 10 durations =============================
0.43s call     integration_tests/security/test_jail.py::test_jailer_bind_mount_propagation[PCI_ON-ro-vmlinux-6.1.172]
0.31s call     integration_tests/security/test_jail.py::test_jailer_bind_mount_propagation[PCI_OFF-ro-vmlinux-6.1.172]
0.01s teardown integration_tests/security/test_jail.py::test_jailer_bind_mount_propagation[PCI_OFF-ro-vmlinux-6.1.172]
0.01s teardown integration_tests/security/test_jail.py::test_jailer_bind_mount_propagation[PCI_ON-ro-vmlinux-6.1.172]
0.01s setup    integration_tests/security/test_jail.py::test_jailer_bind_mount_propagation[PCI_ON-ro-vmlinux-6.1.172]
0.00s setup    integration_tests/security/test_jail.py::test_jailer_bind_mount_propagation[PCI_OFF-ro-vmlinux-6.1.172]
=========================== short test summary info ============================
FAILED integration_tests/security/test_jail.py::test_jailer_bind_mount_propagation[PCI_ON-ro-vmlinux-6.1.172] - RuntimeError: ('Start microvm error: System configuration error: Cannot load kernel due to invalid memory configuration or invalid kernel image: Kernel Loader: failed to load ELF kernel image: Kernel Loader: Unable to read elf header', {'fault_message': 'Start microvm error: System configuration error: Cannot load kernel due to invalid memory configuration or invalid kernel image: Kernel Loader: failed to load ELF kernel image: Kernel Loader: Unable to read elf header'}, <Response [400]>)
FAILED integration_tests/security/test_jail.py::test_jailer_bind_mount_propagation[PCI_OFF-ro-vmlinux-6.1.172] - RuntimeError: ('Start microvm error: System configuration error: Cannot load kernel due to invalid memory configuration or invalid kernel image: Kernel Loader: failed to load ELF kernel image: Kernel Loader: Unable to read elf header', {'fault_message': 'Start microvm error: System configuration error: Cannot load kernel due to invalid memory configuration or invalid kernel image: Kernel Loader: failed to load ELF kernel image: Kernel Loader: Unable to read elf header'}, <Response [400]>)
============================== 2 failed in 0.90s ===============================
[Firecracker devtool] Finished test run ...

The 400 response and "Unable to read elf header" message match #1089 (comment) , confirming the test reproduces the original bug when the fix is reverted.

Reason

Closes #1099

License Acceptance

By submitting this pull request, I confirm that my contribution is made under
the terms of the Apache 2.0 license. For more information on following Developer
Certificate of Origin and signing off your commits, please check
CONTRIBUTING.md.

PR Checklist

  • I have read and understand CONTRIBUTING.md.
  • I have run tools/devtool checkbuild --all to verify that the PR passes
    build checks on all supported architectures.
  • I have run tools/devtool checkstyle to verify that the PR passes the
    automated style checks.
  • I have described what is done in these changes, why they are needed, and
    how they are solving the problem in a clear and encompassing way.
  • I have updated any relevant documentation (both in code and in the docs)
    in the PR.
  • I have mentioned all user-facing changes in CHANGELOG.md.
  • If a specific issue led to this PR, this PR closes the issue.
  • When making API changes, I have followed the
    Runbook for Firecracker API changes.
  • I have tested all new and changed functionalities in unit tests and/or
    integration tests.
  • I have linked an issue to every new TODO.

  • This functionality cannot be added in rust-vmm.

Comment thread tests/integration_tests/security/test_jail.py Outdated
Comment thread tests/integration_tests/security/test_jail.py Outdated

@not4s not4s 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.

Thanks for contributing! Would you mind rebasing onto main and dropping the merge commit? I've also left a few comments and would love to hear your thoughts.

@xxgj

xxgj commented Jun 12, 2026

Copy link
Copy Markdown
Author

Would you mind rebasing onto main and dropping the merge commit?

Apologies for the misclick. Rebased onto latest main and it should be a single commit now.

I've also left a few comments and would love to hear your thoughts.

Thanks for the review! Comments are replied above and let me know if you would like to discuss further:)

@codecov

codecov Bot commented Jun 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 83.00%. Comparing base (ac42726) to head (ed65ffe).

⚠️ Current head ed65ffe differs from pull request most recent head 41bdb86

Please upload reports for the commit 41bdb86 to get more accurate results.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #5939   +/-   ##
=======================================
  Coverage   82.99%   83.00%           
=======================================
  Files         277      277           
  Lines       30121    30132   +11     
=======================================
+ Hits        24998    25010   +12     
+ Misses       5123     5122    -1     
Flag Coverage Δ
5.10-m5n.metal 83.30% <ø> (+0.01%) ⬆️
5.10-m6a.metal 82.65% <ø> (+<0.01%) ⬆️
5.10-m6g.metal 79.93% <ø> (+<0.01%) ⬆️
5.10-m6i.metal 83.30% <ø> (+0.01%) ⬆️
5.10-m7a.metal-48xl 82.64% <ø> (+0.01%) ⬆️
5.10-m7g.metal 79.94% <ø> (+0.01%) ⬆️
5.10-m7i.metal-24xl 83.28% <ø> (+0.01%) ⬆️
5.10-m7i.metal-48xl 83.28% <ø> (+<0.01%) ⬆️
5.10-m8g.metal-24xl 79.93% <ø> (+<0.01%) ⬆️
5.10-m8g.metal-48xl 79.93% <ø> (+<0.01%) ⬆️
5.10-m8i.metal-48xl 83.28% <ø> (+<0.01%) ⬆️
5.10-m8i.metal-96xl 83.28% <ø> (+0.01%) ⬆️
6.1-m5n.metal 83.33% <ø> (+0.01%) ⬆️
6.1-m6a.metal 82.67% <ø> (+0.01%) ⬆️
6.1-m6g.metal 79.93% <ø> (+<0.01%) ⬆️
6.1-m6i.metal 83.33% <ø> (+0.01%) ⬆️
6.1-m7a.metal-48xl 82.66% <ø> (+0.01%) ⬆️
6.1-m7g.metal 79.93% <ø> (+<0.01%) ⬆️
6.1-m7i.metal-24xl 83.34% <ø> (+0.01%) ⬆️
6.1-m7i.metal-48xl 83.34% <ø> (+<0.01%) ⬆️
6.1-m8g.metal-24xl 79.94% <ø> (+0.01%) ⬆️
6.1-m8g.metal-48xl 79.94% <ø> (+0.01%) ⬆️
6.1-m8i.metal-48xl 83.34% <ø> (+0.01%) ⬆️
6.1-m8i.metal-96xl 83.34% <ø> (+0.01%) ⬆️
6.18-m5n.metal 83.32% <ø> (-0.01%) ⬇️
6.18-m6a.metal 82.67% <ø> (+0.01%) ⬆️
6.18-m6g.metal 79.93% <ø> (+<0.01%) ⬆️
6.18-m6i.metal 83.32% <ø> (+0.01%) ⬆️
6.18-m7a.metal-48xl 82.66% <ø> (+0.01%) ⬆️
6.18-m7g.metal 79.93% <ø> (+<0.01%) ⬆️
6.18-m7i.metal-24xl 83.35% <ø> (+0.01%) ⬆️
6.18-m7i.metal-48xl 83.34% <ø> (+0.01%) ⬆️
6.18-m8g.metal-24xl 79.94% <ø> (+0.01%) ⬆️
6.18-m8g.metal-48xl 79.94% <ø> (+0.01%) ⬆️
6.18-m8i.metal-48xl 83.34% <ø> (+0.01%) ⬆️
6.18-m8i.metal-96xl 83.35% <ø> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@not4s

This comment was marked as resolved.

not4s
not4s previously approved these changes Jun 15, 2026
@xxgj

xxgj commented Jun 15, 2026

Copy link
Copy Markdown
Author

No worries at all!

Rebased and got the DCO check passing.

Thanks again for your time and effort :)

Bind mounts established on the host inside the chroot before jailer
start must propagate into the jailer's mount namespace. The test
bind-mounts kernel and rootfs onto empty placeholders in the chroot and
drives the API directly (bypassing basic_config to avoid
create_jailed_resource hardlinking over the mounts), then asserts a
clean SSH boot.

Signed-off-by: Junren Chen <xxgj@outlook.com>
@xxgj

xxgj commented Jun 16, 2026

Copy link
Copy Markdown
Author

Hi @not4s ,

Sorry for the back-and-forth :(

It seems the rebase commit may have invalidated your prior approval, so this might need another look..

It also appears two approvals are required, should I request a second reviewer?

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.

Add jailer bind mounts integration test

3 participants