Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 36
test(e2e): reproduce constrained dev shm failure#522
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Uh oh!
There was an error while loading. Please reload this page.
wan9chi marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| #![cfg(target_os = "linux")] | ||
| use std::{os::unix::process::ExitStatusExt as _, process::Command}; | ||
| use anyhow::{Context as _, Result}; | ||
| use nix::{ | ||
| mount::{MsFlags, mount}, | ||
| sched::{CloneFlags, unshare}, | ||
| unistd::{Gid, Uid}, | ||
| }; | ||
| const USAGE: &str = "Usage: vtt small_dev_shm <command> [args...]"; | ||
| pub fn run(args: &[String]) -> Result<()> { | ||
| let (program, command_args) = parse_command(args)?; | ||
| run_platform(program, command_args) | ||
| } | ||
| fn parse_command(args: &[String]) -> Result<(&str, &[String])> { | ||
| args.split_first().map(|(program, args)| (program.as_str(), args)).context(USAGE) | ||
| } | ||
| fn run_platform(program: &str, command_args: &[String]) -> Result<()> { | ||
| let uid = Uid::current().as_raw(); | ||
| let gid = Gid::current().as_raw(); | ||
| unshare(CloneFlags::CLONE_NEWUSER | CloneFlags::CLONE_NEWNS) | ||
| .context("unshare user and mount namespaces")?; | ||
| std::fs::write("/proc/self/uid_map", format!("0 {uid} 1\n")) | ||
| .context("write /proc/self/uid_map")?; | ||
| match std::fs::write("/proc/self/setgroups", "deny") { | ||
| Ok(()) => {} | ||
| Err(error) if error.kind() == std::io::ErrorKind::NotFound => {} | ||
| Err(error) => return Err(error).context("write /proc/self/setgroups"), | ||
| } | ||
| std::fs::write("/proc/self/gid_map", format!("0 {gid} 1\n")) | ||
| .context("write /proc/self/gid_map")?; | ||
| mount(None::<&str>, "/", None::<&str>, MsFlags::MS_REC | MsFlags::MS_PRIVATE, None::<&str>) | ||
| .context("make / recursively private")?; | ||
| mount( | ||
| Some("tmpfs"), | ||
| "/dev/shm", | ||
| Some("tmpfs"), | ||
| MsFlags::empty(), | ||
| Some("nr_blocks=1,huge=never"), | ||
| ) | ||
| .context("mount one-page tmpfs at /dev/shm")?; | ||
| let status = Command::new(program) | ||
| .args(command_args) | ||
| .status() | ||
| .context("run command with constrained /dev/shm")?; | ||
| let code = status.code().unwrap_or_else(|| status.signal().map_or(1, |signal| 128 + signal)); | ||
| std::process::exit(code); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| use std::{error::Error, io}; | ||
| const USAGE: &str = "Usage: vtt stat_long_filename <count>"; | ||
| pub fn run(args: &[String]) -> Result<(), Box<dyn Error>> { | ||
| let count = parse_count(args)?; | ||
| access_generated_path(count, metadata)?; | ||
| Ok(()) | ||
| } | ||
| fn parse_count(args: &[String]) -> Result<usize, String> { | ||
| let [count] = args else { return Err(USAGE.to_owned()) }; | ||
| count.parse().map_err(|_| USAGE.to_owned()) | ||
| } | ||
| fn generated_path(count: usize) -> String { | ||
| "x".repeat(count) | ||
| } | ||
| fn access_generated_path( | ||
| count: usize, | ||
| mut metadata: impl FnMut(&str) -> io::Result<()>, | ||
| ) -> io::Result<()> { | ||
| let path = generated_path(count); | ||
| match metadata(&path) { | ||
wan9chi marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| Ok(()) => Ok(()), | ||
| Err(error) | ||
| if error.kind() == io::ErrorKind::NotFound | ||
| || error.raw_os_error() == Some(libc::ENAMETOOLONG) => | ||
| { | ||
| Ok(()) | ||
| } | ||
| Err(error) => Err(error), | ||
| } | ||
| } | ||
| fn metadata(path: &str) -> io::Result<()> { | ||
| std::fs::metadata(path).map(|_| ()) | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| {} |
wan9chi marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| [[e2e]] | ||
| name = "constrained_dev_shm" | ||
| comment = """ | ||
| Mounting a one-page `/dev/shm` reproduces the SIGBUS seen before fspy moved its shared-memory backing to memfd. | ||
| """ | ||
| platform = "linux-gnu" | ||
wan9chi marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| ignore = true | ||
| steps = [["vtt", "small_dev_shm", "vt", "run", "stress"]] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| # constrained_dev_shm | ||
| Mounting a one-page `/dev/shm` reproduces the SIGBUS seen before fspy moved its shared-memory backing to memfd. | ||
| ## `vtt small_dev_shm vt run stress` | ||
| **Exit code:** 135 | ||
| ``` | ||
| $ vtt stat_long_filename 1048576 | ||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| { | ||
| "tasks": { | ||
| "stress": { | ||
| "command": "vtt stat_long_filename 1048576", | ||
| "cache": true | ||
| } | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On Linux systems whose libc does not export
statx(for example older glibc targets), this LD_PRELOAD library still exportsstatx, so code that weak-links ordlsymsstatxwill call this shim instead of taking its ownSYS_statxfallback. ReturningENOSYShere changes those traced tasks from a working kernelstatxcall into a failure; please invoke the rawSYS_statxpath (and record the access) whenRTLD_NEXThas nostatxrather than exposing a stub.Useful? React with 👍 / 👎.