From fab447cb207688277788c4d1acfc8a13b431057e Mon Sep 17 00:00:00 2001 From: wangjianyu3 Date: Fri, 11 Sep 2026 16:35:06 +0800 Subject: [PATCH 1/2] fs/inode: fix use-after-scope of search path buffer under alloca _inode_search() allocates desc->buffer via lib_get_tempbuffer() and exports it through desc->path/desc->relpath to its callers, which read those fields after _inode_search() has returned and only then release the buffer via RELEASE_SEARCH(). When CONFIG_LIBC_TEMPBUFFER=n, lib_get_tempbuffer() expands to alloca(), whose lifetime ends when _inode_search() returns. The exported pointer therefore dangles, causing a use-after-scope that has been observed as an intermittent zero-byte boot hang on rv-virt:smp (notably with CONFIG_FS_LINKS=y softlink paths). The search path buffer is inherently required to outlive the allocating frame (its lifetime is bound to the caller-owned struct inode_search_s), so alloca is fundamentally unsuitable here. Allocate it from the fs heap instead and free it in RELEASE_SEARCH(). The ~30 SETUP_SEARCH/ RELEASE_SEARCH call sites are unchanged. Assisted-by: OpenCode:claude-opus-4.8 Signed-off-by: wangjianyu3 --- fs/inode/fs_inodesearch.c | 6 +++--- fs/inode/inode.h | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/fs/inode/fs_inodesearch.c b/fs/inode/fs_inodesearch.c index fac611a7c8f57..b43eb3c0654d6 100644 --- a/fs/inode/fs_inodesearch.c +++ b/fs/inode/fs_inodesearch.c @@ -429,7 +429,7 @@ static int _inode_search(FAR struct inode_search_s *desc) buflen = PATH_MAX; } - desc->buffer = lib_get_tempbuffer(buflen); + desc->buffer = fs_heap_malloc(buflen); if (desc->buffer == NULL) { return -ENOMEM; @@ -578,7 +578,7 @@ static int _inode_search(FAR struct inode_search_s *desc) { FAR char *buffer = NULL; - buffer = lib_get_tempbuffer(PATH_MAX); + buffer = fs_heap_malloc(PATH_MAX); if (buffer == NULL) { ret = -ENOMEM; @@ -587,7 +587,7 @@ static int _inode_search(FAR struct inode_search_s *desc) { snprintf(buffer, PATH_MAX, "%s/%s", desc->relpath, name); - lib_put_tempbuffer(desc->buffer); + fs_heap_free(desc->buffer); desc->buffer = buffer; relpath = buffer; ret = OK; diff --git a/fs/inode/inode.h b/fs/inode/inode.h index 79a241e6dcce9..08fc76325100e 100644 --- a/fs/inode/inode.h +++ b/fs/inode/inode.h @@ -41,6 +41,8 @@ #include #include +#include "fs_heap.h" + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -63,7 +65,7 @@ { \ if ((d)->buffer != NULL) \ { \ - lib_put_tempbuffer((d)->buffer); \ + fs_heap_free((d)->buffer); \ (d)->buffer = NULL; \ } \ } \ From a33f16398fa5e5afcadf45ec66700f462dc39991 Mon Sep 17 00:00:00 2001 From: wangjianyu3 Date: Fri, 11 Sep 2026 16:35:06 +0800 Subject: [PATCH 2/2] libc: fix use-after-scope of path buffers under alloca lib_get_pathbuffer() / lib_put_pathbuffer() were defined in terms of lib_get_tempbuffer() / lib_put_tempbuffer(). With CONFIG_LIBC_TEMPBUFFER=n, lib_get_tempbuffer() expands to alloca() and lib_put_tempbuffer() is a no-op, so a path buffer stays valid only until the function that allocated it returns. Several callers let the buffer outlive that frame. For example file_get_path() obtains the path with lib_get_pathbuffer() and returns it to file_close(), which reads it later via notify_close() (CONFIG_FS_NOTIFY=y); under alloca the returned pointer dangles once file_get_path() returns, a use-after-scope. These two macros are defined outside the CONFIG_LIBC_TEMPBUFFER guard, so back them with lib_malloc(PATH_MAX) / lib_free() unconditionally. A path buffer is then always heap-backed and its lifetime is decoupled from the allocating function's stack frame, fixing the escape at its source for every lib_get_pathbuffer() caller, not just file_close(). All callers already pair get with put, so turning the release from a no-op into lib_free() neither leaks nor double-frees. Assisted-by: OpenCode:claude-opus-4.8 Signed-off-by: wangjianyu3 --- include/nuttx/lib/lib.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/nuttx/lib/lib.h b/include/nuttx/lib/lib.h index c6d7e7ada8dc0..8435f183245d1 100644 --- a/include/nuttx/lib/lib.h +++ b/include/nuttx/lib/lib.h @@ -130,8 +130,8 @@ void lib_put_tempbuffer(FAR char *buffer); # define lib_put_tempbuffer(b) #endif -#define lib_get_pathbuffer() lib_get_tempbuffer(PATH_MAX) -#define lib_put_pathbuffer(b) lib_put_tempbuffer(b) +#define lib_get_pathbuffer() lib_malloc(PATH_MAX) +#define lib_put_pathbuffer(b) lib_free(b) /* Functions defined in lib_realpath.c **************************************/