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 b2550e72c860e3f76006f9d9e0d7c4cf24f2320a Author: Marco Casaroli <[email protected]> AuthorDate: Mon Oct 12 05:21:35 2026 +0200 fs/v9fs: Check the name lengths of symlink() and link(). The Tsymlink request had room for 2 * NAME_MAX bytes of name and target, but the target of a symbolic link can be PATH_MAX bytes long: a longer target was copied past the end of the request on the stack. The Tlink request did not check its name length either. Make the Tsymlink request big enough for a NAME_MAX name and a PATH_MAX target, take it from a temporary buffer instead of the stack, and return ENAMETOOLONG for a longer name or target. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marco Casaroli <[email protected]> --- fs/v9fs/client.c | 64 +++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 19 deletions(-) diff --git a/fs/v9fs/client.c b/fs/v9fs/client.c index c63d24d7a51..5ea197f5eb7 100644 --- a/fs/v9fs/client.c +++ b/fs/v9fs/client.c @@ -384,7 +384,7 @@ begin_packed_struct struct v9fs_symlink_s struct v9fs_header_s header; uint32_t fid; uint16_t name_len; - uint8_t buffer[V9FS_BIT16SZ + 2 * NAME_MAX + V9FS_BIT32SZ]; + uint8_t buffer[NAME_MAX + V9FS_BIT16SZ + PATH_MAX + V9FS_BIT32SZ]; } end_packed_struct; #define v9fs_rsymlink_s v9fs_rattach_s @@ -2300,42 +2300,63 @@ int v9fs_client_symlink(FAR struct v9fs_client_s *client, uint32_t fid, FAR const char *name, FAR const char *symtgt, int mode) { - struct v9fs_symlink_s request; + FAR struct v9fs_symlink_s *request; + FAR char *sbuf; struct v9fs_rsymlink_s response; struct iovec wiov[1]; struct iovec riov[1]; uint32_t gid = getgid(); off_t offset = 0; uint16_t symtgt_len; + size_t name_len; + uint16_t tag; + int ret; /* size[4] Tsymlink tag[2] fid[4] name[s] symtgt[s] gid[4] * size[4] Rsymlink tag[2] qid[13] */ - request.fid = fid; - request.name_len = strlen(name); - symtgt_len = strlen(symtgt); - request.header.size = V9FS_HDRSZ + V9FS_BIT32SZ * 2 + V9FS_BIT16SZ * 2 + - request.name_len + symtgt_len; - request.header.type = V9FS_TSYMLINK; - request.header.tag = v9fs_get_tagid(client); + name_len = strlen(name); + symtgt_len = strnlen(symtgt, PATH_MAX); + if (name_len > NAME_MAX || symtgt_len >= PATH_MAX) + { + return -ENAMETOOLONG; + } - memcpy(&request.buffer[offset], name, request.name_len); - offset += request.name_len; - memcpy(&request.buffer[offset], &symtgt_len, V9FS_BIT16SZ); + /* The request is too big for the stack */ + + sbuf = lib_get_tempbuffer(sizeof(struct v9fs_symlink_s)); + if (sbuf == NULL) + { + return -ENOMEM; + } + + request = (FAR struct v9fs_symlink_s *)sbuf; + + tag = v9fs_get_tagid(client); + request->fid = fid; + request->name_len = name_len; + request->header.size = V9FS_HDRSZ + V9FS_BIT32SZ * 2 + + V9FS_BIT16SZ * 2 + name_len + symtgt_len; + request->header.type = V9FS_TSYMLINK; + request->header.tag = tag; + + memcpy(&request->buffer[offset], name, name_len); + offset += name_len; + memcpy(&request->buffer[offset], &symtgt_len, V9FS_BIT16SZ); offset += V9FS_BIT16SZ; - memcpy(&request.buffer[offset], symtgt, symtgt_len); + memcpy(&request->buffer[offset], symtgt, symtgt_len); offset += symtgt_len; - memcpy(&request.buffer[offset], &gid, V9FS_BIT32SZ); + memcpy(&request->buffer[offset], &gid, V9FS_BIT32SZ); - wiov[0].iov_base = &request; - wiov[0].iov_len = V9FS_HDRSZ + V9FS_BIT32SZ * 2 + V9FS_BIT16SZ * 2 + - request.name_len + symtgt_len; + wiov[0].iov_base = request; + wiov[0].iov_len = request->header.size; riov[0].iov_base = &response; riov[0].iov_len = V9FS_HDRSZ + V9FS_QIDSZ; - return v9fs_client_rpc(client->transport, wiov, 1, riov, 1, - request.header.tag); + ret = v9fs_client_rpc(client->transport, wiov, 1, riov, 1, tag); + lib_put_tempbuffer(sbuf); + return ret; } /**************************************************************************** @@ -2354,6 +2375,11 @@ int v9fs_client_link(FAR struct v9fs_client_s *client, uint32_t dfid, * size[4] Rlink tag[2] */ + if (strlen(name) > NAME_MAX) + { + return -ENAMETOOLONG; + } + request.dfid = dfid; request.fid = fid; request.name_len = strlen(name);
