I've been following up on this with some disassembly and debugging to try and figure out what precisely is going wrong. WSL2's "drvfs" is just a 9P2000.L file server implementation (yep, that's the protocol from Plan 9) exposed over a Hyper-V Socket. (On the Windows side, this is known as a VirtIO socket; on the Linux side, however, that means something different and they're called AF_VSOCK.) The 9P server itself is hard to find because it's not in WSL-specific code -- it's baked into the Hyper-V "VSMB" infrastructure for running Linux containers, which predates WSL entirely. The actual server code is in vp9fs.dll, which is loaded by both the WSL2 VM's vmwp.exe instance and a copy of dllhost.exe which it starts with the token of the user who started the WSL2 distro. Because the actual file system operations occur in the dllhost.exe instance they can use the proper security token instead of doing everything as SYSTEM.
The relevant ETW GUID is e13c8d52-b153-571f-78c5-1d4098af2a1e. This took way too long to find out, but allows you to build debugging logs of what the 9P server is doing by using the tracelog utility.
tracelog -start p9trace -guid "#e13c8d52-b153-571f-78c5-1d4098af2a1e" -f R:\p9trace.etl
<do the stuff>
tracelog -stop p9trace
The directory listing failure is reported with a "Reply_Rlerror" message with an error code of 5. Unfortunately, the server has conveniently translated the Windows-side NTSTATUS error code into a Linux-style error.h code, turning anything it doesn't recognize into a catch-all "I/O error" in the process. Luckily, debugging reveals that the underlying error in this case is an NTSTATUS of 0xC00000E5 (STATUS_INTERNAL_ERROR) returned by a call to ZwQueryDirectoryFile.
This ZwQueryDirectoryFile call requests the new-to-Win10 FileInformationClass of FileIdExtdDirectoryInformation (60), which is supposed to return a structure with an extra ReparsePointTag field -- which will be zero in almost all cases because most things aren't reparse points. Changing the FileInformationClass parameter to the older FileIdFullDirectoryInformation (38) prevents the error, though it results in several letters being chopped off of the front of each filename because the 9P server expects the larger struct and has the wrong offsets baked in.
So things would probably work much better if CoveFs supported that newfangled FileIdExtdDirectoryInformation option and the associated FILE_ID_EXTD_DIR_INFO struct; it looks like that should be fairly simple. That's not to say that other WSL2-specific issues aren't also present, but being able to list directories would give us a fighting chance to work around other issues on the Linux side of things.