This is an automated email from the ASF dual-hosted git repository.

casaroli pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 7e5e08c1b74 fs/tmpfs: zero-fill the hole created by a seek-past-EOF 
write.
7e5e08c1b74 is described below

commit 7e5e08c1b745c26cf1b26f56b1ccfe58403ef2cc
Author: Junbo Zheng <[email protected]>
AuthorDate: Mon Oct 26 21:26:38 2026 +0800

    fs/tmpfs: zero-fill the hole created by a seek-past-EOF write.
    
    A write that starts past EOF grows the file storage with realloc(),
    which leaves the gap below the write offset filled with stale heap
    contents instead of zeros, so a reader of the file can observe
    kernel heap residue. tmpfs_truncate() already zeroes the region it
    grows; make the write path do the same for the gap.
    
    Testing:
    Built and ran sim:nsh with tmpfs enabled:
    
      cmake -B build -DBOARD_CONFIG=sim:nsh
      (set CONFIG_FS_TMPFS=y and its guard/blocksize sub-options in
       build/.config)
      cmake --build build -j
      printf 'hello\npoweroff\n' | ./build/nuttx
    
    Test vehicle (applied to apps/examples/hello/hello_main.c):
    
    --- a/apps/examples/hello/hello_main.c
    +++ b/apps/examples/hello/hello_main.c
    @@ -23,7 +23,11 @@
      
****************************************************************************/
    
     #include <nuttx/config.h>
    +
    +#include <fcntl.h>
     #include <stdio.h>
    +#include <string.h>
    +#include <unistd.h>
    
     
/****************************************************************************
      * Public Functions
    @@ -35,6 +39,32 @@
    
     int main(int argc, FAR char *argv[])
     {
    -  printf("Hello, World!!\n");
    +  unsigned char buf[256];
    +  ssize_t n;
    +  int fd;
    +  int dirty;
    +  int i;
    +
    +  fd = open("/tmp/f1", O_CREAT | O_WRONLY | O_TRUNC, 0644);
    +  lseek(fd, 100, SEEK_SET);
    +  write(fd, "X", 1);
    +  close(fd);
    +
    +  fd = open("/tmp/f1", O_RDONLY);
    +  memset(buf, 0, sizeof(buf));
    +  n = read(fd, buf, sizeof(buf));
    +  close(fd);
    +
    +  dirty = 0;
    +  for (i = 0; i < 100; i++)
    +    {
    +      if (buf[i] != 0)
    +        {
    +          dirty++;
    +        }
    +    }
    +
    +  printf("sparse write: size=%zd dirty-gap-bytes=%d (expect 0)\n",
    +         n, dirty);
       return 0;
     }
    
    Observed before the fix (stale heap bytes leak into the file; the
    exact count varies with heap state, 10-12 across runs):
    
      sparse write: size=101 dirty-gap-bytes=12
    
    and after the fix (deterministic, the gap is zeroed):
    
      sparse write: size=101 dirty-gap-bytes=0
    
    Signed-off-by: Junbo Zheng <[email protected]>
---
 fs/tmpfs/fs_tmpfs.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/fs/tmpfs/fs_tmpfs.c b/fs/tmpfs/fs_tmpfs.c
index 51173964ed7..e9fcbcdad50 100644
--- a/fs/tmpfs/fs_tmpfs.c
+++ b/fs/tmpfs/fs_tmpfs.c
@@ -1942,11 +1942,22 @@ static ssize_t tmpfs_write(FAR struct file *filep, FAR 
const char *buffer,
     {
       /* Reallocate the file to handle the write past the end of the file. */
 
+      size_t oldsize = tfo->tfo_size;
+
       ret = tmpfs_realloc_file(tfo, (size_t)endpos);
       if (ret < 0)
         {
           goto errout_with_lock;
         }
+
+      /* A seek past EOF followed by a write leaves a hole that must read
+       * back as zeros; realloc() leaves the gap unzeroed.
+       */
+
+      if (startpos > oldsize)
+        {
+          memset(&tfo->tfo_data[oldsize], 0, startpos - oldsize);
+        }
     }
 
   /* Copy data from the memory object to the user buffer */

Reply via email to