Skip to content
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

console assets fetch looks subject to races #927

Open
davepacheco opened this issue Apr 14, 2022 · 2 comments
Open

console assets fetch looks subject to races #927

davepacheco opened this issue Apr 14, 2022 · 2 comments
Labels
mvp security Related to security.
Milestone

Comments

@davepacheco
Copy link
Collaborator

I think there's some time-of-check-to-time-of-use issues with the way we serve console asset files. In particular, if you had a/b/c/d, and the code got to "b" and confirmed it wasn't a symlink, and then you changed it to be a symlink to something completely different, I think we'd follow it to some/other/path/c/d.

@davepacheco davepacheco added security Related to security. mvp labels Apr 14, 2022
@david-crespo
Copy link
Contributor

david-crespo commented Apr 17, 2022

I haven't dealt with something like this before. I'm guessing you can't lock down the files so they don't change, but rather make sure when you're pulling a/b/c/d that a, a/b, and a/b/c are not symlinks? I have a hard time picturing how to do this in a way that doesn't leave a tiny window of time where a file could change to a symlink.

For future reference to the fixer, here is the relevant code:

let mut current = root_dir.to_owned(); // start from `root_dir`
for segment in &path {
// If we hit a non-directory thing already and we still have segments
// left in the path, bail. We have nowhere to go.
if !current.is_dir() {
return Err(not_found("expected a directory"));
}
current.push(segment);
// Don't follow symlinks.
// Error means either the user doesn't have permission to pull
// metadata or the path doesn't exist.
let m = current
.symlink_metadata()
.map_err(|_| not_found("failed to get file metadata"))?;
if m.file_type().is_symlink() {
return Err(not_found("attempted to follow a symlink"));
}
}

@davepacheco
Copy link
Collaborator Author

Yeah. There's some discussion on oxidecomputer/dropshot#327. I think this is basically why the openat family of functions exist -- you open the root, then openat the first directory component within the root, fstat it to see if it's a symlink, then openat the next component, etc. There's no opportunity for something you've checked whether it's a symlink to suddenly become something else because you're never referencing it (by name) twice. You're always getting an fd, check that for being a symlink, then opening something relative to the fd instead of an absolute path.

@smklein smklein added this to the MVP milestone Jan 20, 2023
leftwo pushed a commit that referenced this issue Oct 4, 2023
Crucible updates
    all Crucible connections should set TCP_NODELAY (#983)
    Use a fixed size for tag and nonce (#957)
    Log crucible opts on start, order crutest options (#974)
    Lock the Downstairs less (#966)
    Cache dirty flag locally, reducing SQLite operations (#970)
    Make stats mutex synchronous (#961)
    Optimize requeue during flow control conditions (#962)
    Update Rust crate base64 to 0.21.4 (#950)
    Do less in control (#949)
    Fix --flush-per-blocks (#959)
    Fast dependency checking (#916)
    Update actions/checkout action to v4 (#960)
    Use `cargo hakari` for better workspace deps (#956)
    Update actions/checkout digest to 8ade135 (#939)
    Cache block size in Guest (#947)
    Update Rust crate ringbuffer to 0.15.0 (#954)
    Update Rust crate toml to 0.8 (#955)
    Update Rust crate reedline to 0.24.0 (#953)
    Update Rust crate libc to 0.2.148 (#952)
    Update Rust crate indicatif to 0.17.7 (#951)
    Remove unused async (#943)
    Use a synchronous mutex for bw/iop_tokens (#946)
    Make flush ID non-locking (#945)
    Use `oneshot` channels instead of `mpsc` for notification (#918)
    Use a strong type for upstairs negotiation (#941)
    Add a "dynamometer" option to crucible-downstairs (#931)
    Get new work and active count in one lock (#938)
    A bunch of misc test cleanup stuff (#937)
    Wait for a snapshot to finish on all downstairs (#920)
    dsc and clippy cleanup. (#935)
    No need to sort ackable_work (#934)
    Use a strong type for repair ID (#928)
    Keep new jobs sorted (#929)
    Remove state_count function on Downstairs (#927)
    Small cleanup to IOStateCount (#932)
    let cmon and IOStateCount use ClientId (#930)
    Fast return for zero length IOs (#926)
    Use a strong type for client ID (#925)
    A few Crucible Agent fixes (#922)
    Use a newtype for `JobId` (#919)
    Don't pass MutexGuard into functions (#917)
    Crutest updates, rename tests, new options (#911)

Propolis updates
    Update tungstenite crates to 0.20
    Use `strum` crate for enum-related utilities
    Wire up bits for CPUID customization
    PHD: improve artifact store (#529)
    Revert abort-on-panic in 'dev' cargo profile
leftwo added a commit that referenced this issue Oct 5, 2023
Crucible updates
    all Crucible connections should set TCP_NODELAY (#983)
    Use a fixed size for tag and nonce (#957)
    Log crucible opts on start, order crutest options (#974)
    Lock the Downstairs less (#966)
    Cache dirty flag locally, reducing SQLite operations (#970)
    Make stats mutex synchronous (#961)
    Optimize requeue during flow control conditions (#962)
    Update Rust crate base64 to 0.21.4 (#950)
    Do less in control (#949)
    Fix --flush-per-blocks (#959)
    Fast dependency checking (#916)
    Update actions/checkout action to v4 (#960)
    Use `cargo hakari` for better workspace deps (#956)
    Update actions/checkout digest to 8ade135 (#939)
    Cache block size in Guest (#947)
    Update Rust crate ringbuffer to 0.15.0 (#954)
    Update Rust crate toml to 0.8 (#955)
    Update Rust crate reedline to 0.24.0 (#953)
    Update Rust crate libc to 0.2.148 (#952)
    Update Rust crate indicatif to 0.17.7 (#951)
    Remove unused async (#943)
    Use a synchronous mutex for bw/iop_tokens (#946)
    Make flush ID non-locking (#945)
    Use `oneshot` channels instead of `mpsc` for notification (#918)
    Use a strong type for upstairs negotiation (#941)
    Add a "dynamometer" option to crucible-downstairs (#931)
    Get new work and active count in one lock (#938)
    A bunch of misc test cleanup stuff (#937)
    Wait for a snapshot to finish on all downstairs (#920)
    dsc and clippy cleanup. (#935)
    No need to sort ackable_work (#934)
    Use a strong type for repair ID (#928)
    Keep new jobs sorted (#929)
    Remove state_count function on Downstairs (#927)
    Small cleanup to IOStateCount (#932)
    let cmon and IOStateCount use ClientId (#930)
    Fast return for zero length IOs (#926)
    Use a strong type for client ID (#925)
    A few Crucible Agent fixes (#922)
    Use a newtype for `JobId` (#919)
    Don't pass MutexGuard into functions (#917)
    Crutest updates, rename tests, new options (#911)

Propolis updates
    Update tungstenite crates to 0.20
    Use `strum` crate for enum-related utilities
    Wire up bits for CPUID customization
    PHD: improve artifact store (#529)
    Revert abort-on-panic in 'dev' cargo profile

---------

Co-authored-by: Alan Hanson <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
mvp security Related to security.
Projects
None yet
Development

No branches or pull requests

3 participants