Improve diagnostics on forbidden file write
When a guest attempts to write to the file system, it gets a "permission denied" error. For developers not familiar with Spin's stateless model, the reason for this can be non-obvious - after all, Spin itself has permission to write to the mapped directory - and can send them on a wild goose chase.
The current error is certainly the right result to return to the guest, but it might be good if we can provide more information to the operator (developer), indicating to them that:
- Writes are intentionally forbidden by default, because in general Spin runtimes are stateless.
- Writes can be enabled in the CLI environment, although this will hamper portability.
- There is documentation to help you figure out how to achieve what you want to. (TODO: check that there is. Write it if there isn't)
- You should also read the documentation for your target deployment environment because nobody likes surprises.
This is currently tricky because we defer all permissions stuff to Wasmtime - we just preopen the tempdir with read only permissions, so have no opportunity to intercept writes and do something more informative with them.
It may be possible to construct a tracing_subscriber Layer that could intercept appropriate wasi:filesystem errors and turn the first "permission denied" into a console message.
This might be a little tricky to implement well because we wouldn't want tracing to be processing all WASI trace events, but the filtering system is pretty sophisticated and could probably be wrangled into doing something reasonable.
Here is some bindgen output representing one of the tracing events we'd want to inspect: https://github.com/bytecodealliance/wasmtime/blob/66754e245ce04d6624c52e9a073f4510bb30c3b1/crates/component-macro/tests/expanded/simple-wasi_tracing_async.rs#L282-L285
Okay I can do this with a tracing layer but it's all a bit hideously stringy (basically looking for ...wasi::filesystem::types in the event target and not-permitted in the event message). I could do better if I could correlate with the previous event (which records the the open-for-write call) but it is - surprise - not obvious to me how to do that. In its current state I'd not feel confident about it, which combined with the cost of inspecting WASI events (even with filtering) makes me wary of going down this route.
The linked test shows a func_wrap[_async] adding tracing and I did wonder if we could do that ourselves to more accurately detect dubious calls and error returns, and raise a tracing event with a distinguished tag. But again, not obvious to me where and how to do that, and I don't want to go down a rabbit hole for it. But if (if!) it would be simple once the barrier of my ignorance was lifted, it might be a better option.
The linked code is generated by wasmtime bindgen, so probably not worth trying to modify.
You should be able to filter on the span fields which should be accessible via the Context, perhaps most conveniently in a DynFilterFn. I might be very vaguely worried about performance but not enough to research further from my phone...