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

Regression: hard links created by Rust no longer working #2669

Closed
RReverser opened this issue Feb 19, 2021 · 4 comments
Closed

Regression: hard links created by Rust no longer working #2669

RReverser opened this issue Feb 19, 2021 · 4 comments
Labels
bug Incorrect behavior in the current implementation that needs fixing

Comments

@RReverser
Copy link
Contributor

RReverser commented Feb 19, 2021

Originally reported on the Rust repo at rust-lang/rust#82277

I tried this code:

fn main() {
	std::fs::hard_link("/a", "/b").unwrap();
}

I compiled it with --target wasm32-wasi and executed with latest Wasmtime 0.23.0 with wasmtime --mapdir=/::. where the current directory contains valid file a.

I expected to see this happen:

A hard link b is created that points to a.

Instead, this happened:

It fails with an error:

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 28, kind: InvalidInput, message: "Invalid argument" }', temp.rs:2:36
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Error: failed to run main module `temp.wasm`

Caused by:
    0: failed to invoke command default
    1: wasm trap: unreachable
       wasm backtrace:
           0: 0x7b4c - <unknown>!__rust_start_panic
           1: 0x75e5 - <unknown>!rust_panic
           2: 0x71bd - <unknown>!std::panicking::rust_panic_with_hook::hb9189a2ae1f00dd6
           3: 0x6928 - <unknown>!std::panicking::begin_panic_handler::{{closure}}::ha38be87363679287
           4: 0x6869 - <unknown>!std::sys_common::backtrace::__rust_end_short_backtrace::h955bbbeea72dc4a0
           5: 0x7061 - <unknown>!rust_begin_unwind
           6: 0xd0a6 - <unknown>!core::panicking::panic_fmt::h904ce09f3cb14707
           7: 0xdbcc - <unknown>!core::option::expect_none_failed::ha29c9c4296a18e58
           8:  0xfee - <unknown>!core::result::Result<T,E>::unwrap::hcf72e0af954224e8
           9:  0x9b7 - <unknown>!temp::main::hdc57b3c35eac1777
          10:  0xac2 - <unknown>!core::ops::function::FnOnce::call_once::h9d9b1f2044973e11
          11:  0x8ac - <unknown>!std::sys_common::backtrace::__rust_begin_short_backtrace::h0d198c55a40ffd2e
          12:  0xdf2 - <unknown>!std::rt::lang_start::{{closure}}::he287b5106de2dbae
          13: 0x76f6 - <unknown>!std::rt::lang_start_internal::h81003f47a7b429a5
          14:  0xdc6 - <unknown>!std::rt::lang_start::h75812a9706ce1699
          15:  0x9e8 - <unknown>!__original_main
          16:  0x3f9 - <unknown>!_start
       note: run with `WASMTIME_BACKTRACE_DETAILS=1` environment variable to display more information

Meta

rustc --version --verbose:

rustc 1.49.0 (e1884a8e3 2020-12-29)
binary: rustc
commit-hash: e1884a8e3c3e813aada8254edfa120e85bf5ffca
commit-date: 2020-12-29
host: x86_64-unknown-linux-gnu
release: 1.49.0

wasmtime --version:

wasmtime 0.23.0

Other attempts

Equivalent C code

I've also tried to compile an equivalent C code:

#include <unistd.h>

int main() {
	return link("/a", "/b");
}

When this is compiled with WASI SDK clang --target=wasm32-wasi and executed with the same command in Wasmtime, it successfully creates the hardlink.

Node.js WASI

I've also tried to execute those Wasm files with Node.js WASI support, and both Wasm files create hard links successfully.

Older Wasmtime

Finally, I've tried to execute both with Wasmtime 0.22, and both also create hardlinks successfully, indicating a regression in Wasmtime itself.

@RReverser RReverser added the bug Incorrect behavior in the current implementation that needs fixing label Feb 19, 2021
@tschneidereit
Copy link
Member

Thank you for reporting this, Ingvar!

cc @sunfishcode and @pchickey

@RReverser RReverser changed the title Regression: hard links creates by Rust no longer working Regression: hard links created by Rust no longer working Feb 19, 2021
@sunfishcode
Copy link
Member

The short answer is it's a bug in Rust's WASI support; see rust-lang/rust#81984 for a fix. Shorter-term fixes are also possible, so if you need something sooner, let's discuss it.

The longer answer is:

POSIX's linkat function has a flags argument which can be AT_SYMLINK_FOLLOW, allowing the user to control whether symlinks are followed. Unlike open's O_NOFOLLOW however, which fails on a symlink, linkat without AT_SYMLINK_FOLLOW succeeds and simply creates a link to the symlink.

WASI's link function is modeled after CloudABI's which is modeled after POSIX's, so it has an equivalent of AT_SYMLINK_FOLLOW. However, it's not safe to implement it in terms of a host call to linkat with AT_SYMLINK_FOLLOW set, because that would blindly follow the symlink and could link to something outside the sandbox. Since there's no way to make linkat fail on a symlink, there's no way to implement a sandboxed linkat with AT_SYMLINK_FOLLOW without introducing race conditions.

linkat with AT_SYMLINK_FOLLOW is rare in practice anyway, so I'm preparing to propose a change to WASI to not support it. Wasmtime is admittedly ahead of the curve in that it already doesn't support it. Creating hard links is pretty uncommon in general, and even moreso in code intended to be portable, so I guessed that this might not come up, but I appear to have been wrong :-}.

@RReverser
Copy link
Contributor Author

@sunfishcode Thanks for the detailed explanation! It's always exciting to be hitting bugs that live in a crossover of spec and several implementations 😅

@bjorn3
Copy link
Contributor

bjorn3 commented Feb 9, 2023

rust-lang/rust#81984 has been merged. Can this be closed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Incorrect behavior in the current implementation that needs fixing
Projects
None yet
Development

No branches or pull requests

5 participants