diff --git a/src/native/libs/System.Native/pal_mount.c b/src/native/libs/System.Native/pal_mount.c index 386eba5ede1162..11403005df2dff 100644 --- a/src/native/libs/System.Native/pal_mount.c +++ b/src/native/libs/System.Native/pal_mount.c @@ -4,12 +4,14 @@ #include "pal_config.h" #include "pal_mount.h" #include "pal_utilities.h" +#include "pal_safecrt.h" #include #include #include #include +#include -// Check if we should use getmntinfo or /proc/mounts +// Check if we should use getfsstat or /proc/mounts #if HAVE_MNTINFO #include #else @@ -32,18 +34,83 @@ int32_t SystemNative_GetAllMountPoints(MountPointFound onFound, void* context) { #if HAVE_MNTINFO - // getmntinfo returns pointers to OS-internal structs, so we don't need to worry about free'ing the object + // Use getfsstat which is thread-safe (unlike getmntinfo which uses internal static buffers) #if HAVE_STATFS struct statfs* mounts = NULL; #else struct statvfs* mounts = NULL; #endif - int count = getmntinfo(&mounts, MNT_WAIT); + + int count; + int capacity = 0; + size_t bufferSize = 0; + + // Loop to handle the case where mount points are added between calls + while (1) + { + // Get the current number of mount points + count = getfsstat(NULL, 0, MNT_NOWAIT); + if (count < 0) + { + free(mounts); + return -1; + } + + // Reallocate buffer if needed - allocate one extra to detect if more mounts were added + if (count >= capacity) + { + free(mounts); + capacity = count + 1; + if (!multiply_s((size_t)capacity, sizeof(*mounts), &bufferSize)) + { + errno = ENOMEM; + return -1; + } + if (bufferSize > INT_MAX) + { + errno = ENOMEM; + return -1; + } +#if HAVE_STATFS + mounts = (struct statfs*)malloc(bufferSize); +#else + mounts = (struct statvfs*)malloc(bufferSize); +#endif + if (mounts == NULL) + { + errno = ENOMEM; + return -1; + } + } + + // If count is 0, break - post-loop code handles empty case + if (count == 0) + { + break; + } + + // Get actual mount point information + count = getfsstat(mounts, (int)bufferSize, MNT_NOWAIT); + if (count < 0) + { + free(mounts); + return -1; + } + + // If count is less than capacity, we got all mount points + if (count < capacity) + { + break; + } + // Otherwise, more mounts were added - loop again with larger buffer + } + for (int32_t i = 0; i < count; i++) { onFound(context, mounts[i].f_mntonname); } + free(mounts); return 0; }