This is an automated email from the ASF dual-hosted git repository. acassis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 30ccba1acc13494fb7e84a2e4e26de0cb9ecd9ad Author: Marco Casaroli <[email protected]> AuthorDate: Mon Oct 12 05:20:30 2026 +0200 fs/v9fs: Truncate the readlink() target, and keep the reply off the stack. v9fs_client_readlink() returned ENAMETOOLONG when the target was longer than the buffer, but readlink() must return the first bytes of the target. It also kept the whole reply, PATH_MAX bytes, on the stack, which is too much for a small kernel stack. Read the reply into a temporary buffer and copy as much of the target as fits. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marco Casaroli <[email protected]> --- fs/v9fs/client.c | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/fs/v9fs/client.c b/fs/v9fs/client.c index 8a4f857d22e..c63d24d7a51 100644 --- a/fs/v9fs/client.c +++ b/fs/v9fs/client.c @@ -408,7 +408,7 @@ begin_packed_struct struct v9fs_rreadlink_s { struct v9fs_header_s header; uint16_t target_len; - uint8_t target[PATH_MAX]; + uint8_t target[]; } end_packed_struct; struct v9fs_map_s @@ -2381,15 +2381,27 @@ ssize_t v9fs_client_readlink(FAR struct v9fs_client_s *client, uint32_t fid, FAR char *buffer, size_t buflen) { struct v9fs_readlink_s request; - struct v9fs_rreadlink_s response; + FAR struct v9fs_rreadlink_s *response; struct iovec wiov[1]; struct iovec riov[1]; + FAR char *rbuf; + size_t len; int ret; /* size[4] Treadlink tag[2] fid[4] * size[4] Rreadlink tag[2] target[s] + * + * The response is too big for the stack. */ + rbuf = lib_get_tempbuffer(sizeof(struct v9fs_rreadlink_s) + PATH_MAX); + if (rbuf == NULL) + { + return -ENOMEM; + } + + response = (FAR struct v9fs_rreadlink_s *)rbuf; + request.fid = fid; request.header.size = V9FS_HDRSZ + V9FS_BIT32SZ; request.header.type = V9FS_TREADLINK; @@ -2397,22 +2409,30 @@ ssize_t v9fs_client_readlink(FAR struct v9fs_client_s *client, uint32_t fid, wiov[0].iov_base = &request; wiov[0].iov_len = V9FS_HDRSZ + V9FS_BIT32SZ; - riov[0].iov_base = &response; - riov[0].iov_len = sizeof(response); + riov[0].iov_base = response; + riov[0].iov_len = sizeof(struct v9fs_rreadlink_s) + PATH_MAX; ret = v9fs_client_rpc(client->transport, wiov, 1, riov, 1, request.header.tag); if (ret < 0) { - return ret; + goto out; } - if (response.target_len > buflen) + if (response->target_len > PATH_MAX) { - return -ENAMETOOLONG; + ret = -EIO; + goto out; } - memcpy(buffer, response.target, response.target_len); - return response.target_len; + /* Like readlink(), truncate the target to the size of the buffer */ + + len = MIN(response->target_len, buflen); + memcpy(buffer, response->target, len); + ret = len; + +out: + lib_put_tempbuffer(rbuf); + return ret; } #endif
