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);

Reply via email to