Re: [PATCH v3 1/3] 9p: skip intermediate directory entry name copy in p9dirent_read()
Christian Schoenebeck <[email protected]>
| Newsgroups | org.kernel.vger.linux-fsdevel,dev.linux.lists.v9fs,org.kernel.vger.linux-kernel,org.kernel.vger.netdev |
|---|---|
| Message-ID | <12972173.O9o76ZdvQC@weasel> |
On Friday, 18 September 2026 04:48:49 CEST Haobin Wu wrote:
> v9fs_dir_readdir_dotl() decodes each entry of a Rreaddir reply with
> p9dirent_read(), which parses it through p9pdu_readf("Qqbs"). The 's'
> conversion in p9pdu_vreadf() already allocates a NUL-terminated copy
> of the name from the wire buffer; p9dirent_read() then strscpy()s that
> copy into the fixed 256-byte p9_dirent::d_name and frees the original.
>
> The wire format carries the name length in 16 bits, so a name longer
> than 255 bytes is valid on the wire and may well be valid on the
> server's filesystem, but it makes strscpy() return -E2BIG.
> v9fs_dir_readdir_dotl() turns that into -EIO and aborts getdents64(),
> so every entry after the long one disappears from the listing.
>
> Drop the second copy: keep the string allocated by p9pdu_vreadf() in
> p9_dirent and let v9fs_dir_readdir_dotl(), its only user, free it once
> dir_emit() has consumed it. p9_dirent is a short-lived stack object, so
> the string's lifetime does not change.
>
> Note that the VFS only rejects names of PATH_MAX bytes or more in
> verify_dirent_name(), so after this change a name between NAME_MAX and
> PATH_MAX is returned by getdents64() even though any later lookup on it
> fails with -ENAMETOOLONG. The next patch skips such entries.
>
> Fixes: 7751bdb3a095 ("9p: readdir implementation for 9p2000.L")
> Closes: https://github.com/microsoft/WSL/issues/41192
> Signed-off-by: Haobin Wu <[email protected]>
Reviewed-by: Christian Schoenebeck <[email protected]>
> ---
> fs/9p/vfs_dir.c | 6 +++++-
> include/net/9p/client.h | 2 +-
> net/9p/protocol.c | 12 ++----------
> 3 files changed, 8 insertions(+), 12 deletions(-)