Fix read() on a directory fd returning EBADF instead of EISDIR - #869
Fix read() on a directory fd returning EBADF instead of EISDIR#869SebTardif wants to merge 2 commits into
Conversation
POSIX requires EISDIR when read() is used on a directory. wasip2 read-via-stream fails with bad-descriptor, which we mapped to EBADF. Remap that error to EISDIR when get_type or fdstat shows a directory. Closes WebAssembly#865 Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
wasip3 read-via-stream returns a stream, not a result. Wasmtime traps with ErrorCode::BadDescriptor on a directory fd, so the later eof remap never runs. Check descriptor_stat before opening the stream. Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
alexcrichton
left a comment
There was a problem hiding this comment.
Thanks! I don't think though that this is something that's best to fix here, however, but rather inside of Wasmtime itself. Needing to perform extra syscalls just to map an error code feels a bit excessive when I think the fix in Wasmtime would probably be just a line or two
Agreed. I opened bytecodealliance/wasmtime#14135 so Once that lands, this libc extra |
When
read()is used on a directory file descriptor, POSIX requiresEISDIR. On wasip2 the hostread-via-streamcall fails withbad-descriptor, andtranslate_errormaps that toEBADF. On wasip3 the same host call traps (ErrorCode::BadDescriptor) becauseread-via-streamreturns a stream, not a result.That is the mismatch rust-lang/rust#160359 and uutils/coreutils#13625 are already working around in userland.
Change
read-via-streamfails withbad-descriptor,get_typeand returnEISDIRif the fd is a directory.descriptor_statbefore opening the stream. Checking after the fact is not possible; the import traps.fd_readfails withBADF/ENOTCAPABLE,fd_fdstat_getand returnEISDIRfor a directory.EBADF(closed or invalid fd) is unchanged. The wasip2 success path does not add a stat.Test
test/src/read-dir-eisdir.c:opena directory,readit, expectEISDIR. Invalid fd stillEBADF. Regular file still reads.CI on the first push: wasip1/p2 passed; wasip3 trapped in
read-via-stream(the p3 pre-check is the follow-up on this branch).References
read(): https://pubs.opengroup.org/onlinepubs/9699919799/functions/read.htmlread-via-streampath in wasip2: Use virtual dispatch in the descriptor table #662Closes #865