arnavsharma990 opened a new issue, #20166:
URL: https://github.com/apache/nuttx/issues/20166

   ### Description / Steps to reproduce the issue
   
   `mtdconfig_unregister_by_path()` in `drivers/mtd/mtd_config.c` frees the 
`mtdconfig_struct_s` object before closing the temporary `struct file` opened 
by the function.
   
   The relevant sequence is:
   
   ```text
   file_open()
     -> mtdconfig_open()
     -> nxmutex_lock(&dev->lock)
     -> dev = inode->i_private
     -> nxmutex_destroy(&dev->lock)
     -> kmm_free(dev)
     -> file_close()
     -> mtdconfig_close()
     -> nxmutex_unlock(&dev->lock)
   ```
   
   `mtdconfig_close()` obtains `dev` from `inode->i_private` and accesses 
`dev->lock`. At that point, `dev` has already been freed by 
`mtdconfig_unregister_by_path()`. The mutex has also already been destroyed 
while held by the temporary open.
   
   This results in a use-after-free and heap corruption without requiring 
concurrency or another open file.
   
   ### Steps to reproduce
   
   1. Build the `sim` target with:
   
      * `CONFIG_MTD=y`
      * `CONFIG_MTD_CONFIG=y`
      * `CONFIG_RAMMTD=y`
      * `CONFIG_RAMMTD_FLASHSIM=y`
      * `CONFIG_MM_FILL_ALLOCATIONS=y`
   
   2. Create a RAM MTD device and register it with:
      `mtdconfig_register_by_path(mtd, "/dev/uafcfg")`
   
   3. Call:
      `mtdconfig_unregister_by_path("/dev/uafcfg")`
   
   4. Observe that `mtdconfig_unregister_by_path()` returns `OK`.
   
   5. Perform a subsequent allocation. The heap is corrupted and the simulator 
terminates with `SIGSEGV` inside `mm_malloc()` while traversing the corrupted 
free list.
   
   ### Reproduction result
   
   The issue was reproduced deterministically on 3 consecutive runs.
   
   Representative output:
   
   ```text
   UAFCHECK: start (mtd_config unregister lifetime probe)
   UAFCHECK control[64]-freed: ptr=0x1002ddae8 len=64 bytes:
     0000: c0 01 e2 04 01 00 00 00 a0 01 e2 04 01 00 00 00
     0010: 55 55 55 55 ... (all 0x55)
   UAFCHECK control non-0x55 bytes past offset 16: 0
   UAFCHECK: mtdconfig_register_by_path ret=0
   UAFCHECK: open /dev/uafcfg fd=3 errno=0
   UAFCHECK: calling mtdconfig_unregister_by_path...
   UAFCHECK: mtdconfig_unregister_by_path ret=0
   <CRASH — nothing further printed>
   ```
   
   The LLDB backtrace from the final validation was:
   
   ```text
   stop reason = EXC_BAD_ACCESS
   * frame #0: nuttx`mm_malloc + 176
   * frame #1: nuttx`malloc + 32
   * frame #2: nuttx`uafcheck_main + 668
   ```
   
   The final probe was a plain `malloc()` performed immediately after 
`mtdconfig_unregister_by_path()`, before any VFS reopen operation. Therefore 
the observed allocator failure does not depend on subsequent VFS activity.
   
   ### Expected behavior
   
   The private `mtdconfig_struct_s` object should remain valid until the 
temporary file has been closed and the driver has been successfully 
unregistered.
   
   The object should not be destroyed or freed while `file.f_inode->i_private` 
can still be accessed by the file close operation.
   
   Additionally, the return value of `unregister_driver()` should be checked 
before freeing the private object. In particular, an `-EBUSY` result must not 
be ignored while existing inode references may still access `i_private`.
   
   ### Current behavior
   
   The current implementation performs:
   
   ```c
   dev = inode->i_private;
   nxmutex_destroy(&dev->lock);
   kmm_free(dev);
   file_close(&file);
   unregister_driver(path);
   return OK;
   ```
   
   while `mtdconfig_close()` performs:
   
   ```c
   FAR struct inode *inode = filep->f_inode;
   FAR struct mtdconfig_struct_s *dev = inode->i_private;
   nxmutex_unlock(&dev->lock);
   ```
   
   Thus `file_close()` accesses the already-freed `dev`.
   
   ### Additional validation
   
   The relevant VFS `file_close()`, inode reference, and `unregister_driver()` 
paths were inspected. The free-before-close pattern was also searched for in 
the repository.
   
   No existing open or closed issue, PR, or fix commit addressing this specific 
`mtdconfig_unregister_by_path()` lifetime violation was found.
   
   The production NuttX source was not modified during runtime validation. The 
temporary reproduction harness was removed afterward, the original `.config` 
was restored, and both `nuttx` and `apps` repositories were left clean.
   
   
   
   ### On which OS does this issue occur?
   
   [OS: Windows], [OS: Mac]
   
   ### What is the version of your OS?
   
   26.6.2
   
   ### NuttX Version
   
   Apache NuttX master — commit 89c2392290b296facc358219161831cad5e1bacd
   
   ### Issue Architecture
   
   [Arch: all]
   
   ### Issue Area
   
   [Area: Drivers]
   
   ### Host information
   
   NuttX configuration options:
     CONFIG_HOST_MACOS=y
     CONFIG_APPS_DIR="../apps"
     CONFIG_BASE_DEFCONFIG="sim:configdata"
     CONFIG_BUILD_FLAT=y
     CONFIG_OUTPUT_STRIP_PATHS=y
     CONFIG_ARCH_HAVE_SETJMP=y
     CONFIG_ARCH_SETJMP_H=y
     CONFIG_ARCH_NONE_DEBUG_H=y
     CONFIG_FORTIFY_SOURCE=0
     CONFIG_NDEBUG=y
     CONFIG_ARCH_HAVE_STACKCHECK=y
     CONFIG_STACK_USAGE_WARNING=0
     CONFIG_DEBUG_SYMBOLS=y
     CONFIG_DEBUG_SYMBOLS_LEVEL="-g"
     CONFIG_ARCH_HAVE_CUSTOMOPT=y
     CONFIG_DEBUG_NOOPT=y
     CONFIG_LTO_NONE=y
     CONFIG_DEBUG_OPT_UNUSED_SECTIONS=y
     CONFIG_DEBUG_LINK_MAP=y
     CONFIG_ARCH_SIM=y
     CONFIG_ARCH="sim"
     CONFIG_ARCH_CHIP="sim"
     CONFIG_HOST_ARM64=y
     CONFIG_SIM_TOOLCHAIN_GCC=y
     CONFIG_SIM_WALLTIME_SLEEP=y
     CONFIG_SIM_WALLTIME_RATIO=100
     CONFIG_SIM_LOOP_INTERVAL=10
     CONFIG_SIM_STACKSIZE_ADJUSTMENT=65536
     CONFIG_SIM_OFFLOAD_NUM_BUFFERS=2
     CONFIG_SIM_OFFLOAD_BUFFER_NUMBYTES=32767
     CONFIG_SIM_UART_DMA=y
     CONFIG_SIM_UART_NUMBER=0
     CONFIG_SIM_CUSTOM_DATA_SECTION=""
     CONFIG_ARCH_TOOLCHAIN_GNU=y
     CONFIG_ARCH_TOOLCHAIN_GCC=y
     CONFIG_ARCH_64BIT=y
     CONFIG_ARCH_HAVE_TEXT_HEAP=y
     CONFIG_ARCH_HAVE_MULTICPU=y
     CONFIG_ARCH_HAVE_VFORK=y
     CONFIG_ARCH_HAVE_POWEROFF=y
     CONFIG_ARCH_HAVE_RTC_SUBSECONDS=y
     CONFIG_ARCH_HAVE_SYSCALL_HOOKS=y
     CONFIG_ARCH_HAVE_BACKTRACE=y
     CONFIG_ARCH_HAVE_CPUINFO=y
     CONFIG_ARCH_CPUINFO_FREQ_KHZ=0
     CONFIG_ARCH_HAVE_TCBINFO=y
     CONFIG_NCPUS=1
     CONFIG_BOARD_LOOPSPERMSEC=-1
     CONFIG_BOOT_RUNFROMFLASH=y
     CONFIG_RAM_START=0x0
     CONFIG_RAM_SIZE=0
     CONFIG_FLASH_START=0x0
     CONFIG_FLASH_SIZE=0
     CONFIG_ARCH_BOARD_SIM=y
     CONFIG_ARCH_BOARD="sim"
     CONFIG_ARCH_HAVE_BUTTONS=y
     CONFIG_ARCH_HAVE_IRQBUTTONS=y
     CONFIG_BOARD_CRASHDUMP_NONE=y
     CONFIG_BOARD_MEMORY_RANGE=""
     CONFIG_DISABLE_OS_API=y
     CONFIG_DISABLE_POSIX_TIMERS=y
     CONFIG_DISABLE_PTHREAD=y
     CONFIG_DISABLE_MQUEUE=y
     CONFIG_DISABLE_MQUEUE_SYSV=y
     CONFIG_ARCH_HAVE_TICKLESS=y
     CONFIG_USEC_PER_TICK=10000
     CONFIG_TIMER_ADJUST_USEC=0
     CONFIG_ARCH_HAVE_TIMEKEEPING=y
     CONFIG_START_YEAR=2013
     CONFIG_START_MONTH=11
     CONFIG_START_DAY=4
     CONFIG_IRQ_NWORKS=8
     CONFIG_IRQ_WORK_SECTION=""
     CONFIG_IRQ_WORK_STACKSIZE=2048
     CONFIG_INIT_ENTRY=y
     CONFIG_INIT_ARGS=""
     CONFIG_INIT_STACKSIZE=2048
     CONFIG_INIT_PRIORITY=100
     CONFIG_INIT_ENTRYPOINT="configdata_main"
     CONFIG_INIT_ENTRYNAME="uafcheck_main"
     CONFIG_RR_INTERVAL=0
     CONFIG_TASK_NAME_SIZE=31
     CONFIG_SCHED_CPULOAD_NONE=y
     CONFIG_SCHED_CPULOAD_TICKSPERSEC=100
     CONFIG_SCHED_PROFILE_TICKSPERSEC=1000
     CONFIG_SCHED_STACK_RECORD=0
     CONFIG_DEV_CONSOLE=y
     CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=8
     CONFIG_FILE_STREAM=y
     CONFIG_BOARD_LATE_INITIALIZE=y
     CONFIG_BOARD_INITTHREAD_STACKSIZE=2048
     CONFIG_BOARD_INITTHREAD_PRIORITY=240
     CONFIG_ENABLE_ALL_SIGNALS=y
     CONFIG_SIG_PREALLOC_IRQ_ACTIONS=8
     CONFIG_SIG_PREALLOC_ACTIONS=4
     CONFIG_SIG_ALLOC_ACTIONS=1
     CONFIG_SCHED_WORKQUEUE=y
     CONFIG_SCHED_HPWORK=y
     CONFIG_SCHED_HPNTHREADS=1
     CONFIG_SCHED_HPWORKPRIORITY=224
     CONFIG_SCHED_HPWORKSTACKSIZE=2048
     CONFIG_SCHED_HPWORKSTACKSECTION=""
     CONFIG_DEFAULT_TASK_STACKSIZE=2048
     CONFIG_IDLETHREAD_STACKSIZE=4096
     CONFIG_PTHREAD_STACK_MIN=256
     CONFIG_PTHREAD_STACK_DEFAULT=2048
     CONFIG_PTHREAD_GUARDSIZE_DEFAULT=0
     CONFIG_PID_INITIAL_COUNT=16
     CONFIG_ONESHOT=y
     CONFIG_ONESHOT_COUNT=y
     CONFIG_ALARM_ARCH=y
     CONFIG_BCH=y
     CONFIG_BCH_BUFFER_ALIGNMENT=0
     CONFIG_DEV_NULL=y
     CONFIG_DEV_ZERO=y
     CONFIG_DEV_OPTEE_NONE=y
     CONFIG_MTD=y
     CONFIG_MTD_BYTE_WRITE=y
     CONFIG_MTD_CONFIG=y
     CONFIG_MTD_CONFIG_BUFFER_SIZE=0
     CONFIG_RAMMTD=y
     CONFIG_RAMMTD_BLOCKSIZE=256
     CONFIG_RAMMTD_ERASESIZE=4096
     CONFIG_RAMMTD_ERASESTATE=0xff
     CONFIG_RAMMTD_FLASHSIM=y
     CONFIG_ARCH_HAVE_SERIAL_TERMIOS=y
     CONFIG_SERIAL=y
     CONFIG_SERIAL_CONSOLE=y
     CONFIG_SERIAL_NPOLLWAITERS=4
     CONFIG_SERIAL_IFLOWCONTROL=y
     CONFIG_SERIAL_TXDMA=y
     CONFIG_SERIAL_RXDMA=y
     CONFIG_SYSLOG=y
     CONFIG_SYSLOG_DEFAULT_MASK=0xff
     CONFIG_SYSLOG_CRLF=y
     CONFIG_SYSLOG_MAX_CHANNELS=1
     CONFIG_SYSLOG_DEVPATH="/dev/ttyS1"
     CONFIG_SYSLOG_DEFAULT=y
     CONFIG_FS_NEPOLL_DESCRIPTORS=8
     CONFIG_FS_LOCK_BUCKET_SIZE=0
     CONFIG_SENDFILE_BUFSIZE=512
     CONFIG_FS_BACKTRACE=0
     CONFIG_FS_ANONMAP=y
     CONFIG_FS_FAT=y
     CONFIG_FS_NXFFS=y
     CONFIG_NXFFS_PREALLOCATED=y
     CONFIG_NXFFS_ERASEDSTATE=0xff
     CONFIG_NXFFS_PACKTHRESHOLD=32
     CONFIG_NXFFS_MAXNAMLEN=255
     CONFIG_NXFFS_TAILTHRESHOLD=8192
     CONFIG_NXFONTS_PACKEDMSFIRST=y
     CONFIG_MM_DEFAULT_MANAGER=y
     CONFIG_MM_DEFAULT_ALIGNMENT=8
     CONFIG_MM_NODE_GUARDSIZE=0
     CONFIG_MM_REGIONS=1
     CONFIG_MM_MAP_COUNT_MAX=1024
     CONFIG_MM_FILL_ALLOCATIONS=y
     CONFIG_MM_BACKTRACE=-1
     CONFIG_MM_FREE_DELAYCOUNT_MAX=0
     CONFIG_MM_HEAP_BIGGEST_COUNT=30
     CONFIG_MM_HEAP_MEMPOOL_THRESHOLD=-1
     CONFIG_BINFMT_ELF_RELOCATABLE=y
     CONFIG_STDIO_BUFFER_SIZE=64
     CONFIG_STDIO_LINEBUFFER=y
     CONFIG_NUNGET_CHARS=2
     CONFIG_LIBC_ATOMIC_TOOLCHAIN=y
     CONFIG_ARCH_LOWPUTC=y
     CONFIG_LIBC_HOMEDIR="/"
     CONFIG_LIBC_TMPDIR="/tmp"
     CONFIG_LIBC_MAX_TMPFILE=32
     CONFIG_LIBC_MAX_EXITFUNS=0
     CONFIG_POSIX_SPAWN_DEFAULT_STACKSIZE=2048
     CONFIG_LIBC_HOSTNAME=""
     CONFIG_LIBC_OPEN_MAX=256
     CONFIG_NAME_MAX=32
     CONFIG_PATH_MAX=256
     CONFIG_LINE_MAX=80
     CONFIG_LIBC_STRERROR_ERRNUM=y
     CONFIG_LIBC_STRSIGNAL=y
     CONFIG_LIBC_STRFTIME_C_STANDARD_FORMATS=y
     CONFIG_LIBC_STRFTIME_POSIX_FORMATS=y
     CONFIG_LIBC_STRFTIME_NONSTANDARD_FORMATS=y
     CONFIG_TLS_TASK_NELEM=0
     CONFIG_TLS_NCLEANUP=0
     CONFIG_LIBC_GAISTRERROR_ERRNUM=y
     CONFIG_LIBC_FTOK_VFS_PATH="/var/ftok"
     CONFIG_LIBC_MEMFD_ERROR=y
     CONFIG_LIBC_TEMPBUFFER=y
     CONFIG_LIBC_MAX_TEMPBUFFER=2
     CONFIG_LIBC_TEMPBUFFER_MALLOC=y
     CONFIG_LIBC_MUTEX_BACKTRACE=0
     CONFIG_STREAM_OUT_BUFFER_SIZE=64
     CONFIG_STREAM_HEXDUMP_BUFFER_SIZE=128
     CONFIG_STREAM_BASE64_BUFFER_SIZE=128
     CONFIG_LIBC_INLINE_QUEUE=y
     CONFIG_LIBM_TOOLCHAIN=y
     CONFIG_BUILTIN_TOOLCHAIN=y
     CONFIG_COVERAGE_NONE=y
     CONFIG_COVERAGE_DEFAULT_PREFIX_STRIP="0"
     CONFIG_COVERAGE_DEFAULT_PREFIX="/data"
     CONFIG_PROFILE_NONE=y
     CONFIG_EXAMPLES_CONFIGDATA=y
     CONFIG_EXAMPLES_CONFIGDATA_NEBLOCKS=4
     CONFIG_EXAMPLES_CONFIGDATA_NLOOPS=10000
     CONFIG_EXAMPLES_CONFIGDATA_SILENT=y
     CONFIG_FSUTILS_MKFATFS=y
     CONFIG_MKFATFS_BUFFER_ALIGNMENT=0
     CONFIG_PLATFORM_CONFIGDATA=y
     CONFIG_SYSTEM_DD=y
     CONFIG_SYSTEM_DD_PROGNAME="dd"
     CONFIG_SYSTEM_DD_PRIORITY=100
     CONFIG_SYSTEM_DD_STACKSIZE=2048
     CONFIG_SYSTEM_DD_STATS=y
     CONFIG_TESTING_NXFFS=y
     CONFIG_TESTING_NXFFS_NEBLOCKS=32
     CONFIG_TESTING_NXFFS_MAXNAME=128
     CONFIG_TESTING_NXFFS_MAXFILE=8192
     CONFIG_TESTING_NXFFS_MAXIO=347
     CONFIG_TESTING_NXFFS_MAXOPEN=512
     CONFIG_TESTING_NXFFS_MOUNTPT="/mnt/nxffs"
     CONFIG_TESTING_NXFFS_NLOOPS=100
   
   Host system OS:
     macOS 26.6.2 Darwin Arnavs-MacBook-Air.local 25.6.0 Darwin Kernel Version 
25.6.0: Fri Jul 31 19:17:12 PDT 2026; 
root:xnu-12377.161.14~5/RELEASE_ARM64_T8103 arm64 arm
   
   Host system PATH:
     /Users/arnavsharma/.local/bin
     /Users/arnavsharma/.antigravity/antigravity/bin
     /opt/anaconda3/bin
     /opt/anaconda3/condabin
     /opt/homebrew/bin
     /opt/homebrew/sbin
     /Users/arnavsharma/.local/bin
     /Library/Frameworks/Python.framework/Versions/3.13/bin
     /usr/local/bin
     /System/Cryptexes/App/usr/bin
     /usr/bin
     /bin
     /usr/sbin
     /sbin
     /var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin
     /var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin
     
/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin
     /pkg/env/global/bin
     /Library/Apple/usr/bin
   
   ### Verification
   
   - [x] I have verified before submitting the report.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to