From 642720e9b4bfd885b0f11814812df120ef7edefd Mon Sep 17 00:00:00 2001 From: Arnav Sharma <2006arnavsharma@gmail.com> Date: Wed, 16 Sep 2026 23:12:10 +0530 Subject: [PATCH] examples/configdata: exercise unregister/register lifetime Add a regression test for apache/nuttx#20166 to the configdata example, which runs automatically in every sim:configdata build. After the normal configdata test loops, close the long-lived descriptor and run a full lifetime cycle on /dev/config: - mtdconfig_unregister() must succeed, - the unregistered device must no longer be openable (ENOENT), - the same MTD device must be registerable again and usable, - a final unregister must succeed, leaving the device unregistered. Before the driver fix this crashes deterministically: the old mtdconfig_unregister_by_path() freed the private device structure before closing its temporary file, so the subsequent open() faults in mm_malloc on the corrupted heap (SIGSEGV observed on sim right after unregister returns). With the fix the whole example, 934706/934706 checks included, completes cleanly. The test uses only generic configdata APIs, so it also passes unchanged under CONFIG_MTD_CONFIG_NVS, whose open/close callbacks are no-ops. Assisted-by: Claude:claude-opus Signed-off-by: Arnav Sharma <2006arnavsharma@gmail.com> --- examples/configdata/configdata_main.c | 85 +++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 4 deletions(-) diff --git a/examples/configdata/configdata_main.c b/examples/configdata/configdata_main.c index 007a9d162..616c936f9 100644 --- a/examples/configdata/configdata_main.c +++ b/examples/configdata/configdata_main.c @@ -342,11 +342,11 @@ static int configdata_fillconfig(void) } #if CONFIG_EXAMPLES_CONFIGDATA_VERBOSE != 0 - printf(" Created entry %04X, %d Len=%d\n", - entry->id, entry->instance, entry->len); + printf(" Created entry %04X, %d Len=%d\n", + entry->id, entry->instance, entry->len); #endif - g_nentries++; - g_ntotalalloc++; + g_nentries++; + g_ntotalalloc++; } } @@ -477,6 +477,7 @@ static int configdata_delentries(void) /* Are there any files to be deleted? */ int nentries = g_nentries - g_ndeleted; + if (nentries < 1) { return 0; @@ -609,6 +610,80 @@ static void configdata_cleardeleted(void) g_ndeleted = 0; } +/**************************************************************************** + * Name: configdata_testunregister + * + * Description: + * Exercise the /dev/config register/unregister lifetime. Unregister + * the device, verify that it can no longer be opened, then register + * it again and verify that it is usable. This is a regression test: + * freeing the private device structure before the temporary file used + * during unregister is closed corrupts the heap and crashes the open + * below. + * + * Input Parameters: + * mtd - Pointer to the MTD device bound to the /dev/config device + * + ****************************************************************************/ + +static void configdata_testunregister(FAR struct mtd_dev_s *mtd) +{ + int fd; + int ret; + + close(g_fd); + g_fd = -1; + + ret = mtdconfig_unregister(); + if (ret < 0) + { + printf("ERROR: /dev/config unregistration failed: %d\n", ret); + fflush(stdout); + exit(3); + } + + fd = open("/dev/config", O_RDONLY); + if (fd >= 0 || errno != ENOENT) + { + printf("ERROR: /dev/config still accessible after unregister: " + "fd=%d errno=%d\n", fd, errno); + fflush(stdout); + + if (fd >= 0) + { + close(fd); + } + + exit(3); + } + + ret = mtdconfig_register(mtd); + if (ret < 0) + { + printf("ERROR: /dev/config re-registration failed: %d\n", ret); + fflush(stdout); + exit(3); + } + + fd = open("/dev/config", O_RDONLY); + if (fd < 0) + { + printf("ERROR: Failed to re-open /dev/config %d\n", errno); + fflush(stdout); + exit(3); + } + + close(fd); + + ret = mtdconfig_unregister(); + if (ret < 0) + { + printf("ERROR: /dev/config final unregistration failed: %d\n", ret); + fflush(stdout); + exit(3); + } +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -786,6 +861,8 @@ int main(int argc, FAR char *argv[]) configdata_delallfiles(); #endif + configdata_testunregister(mtd); + configdata_endmemusage(); fflush(stdout); return 0;