From: VMware, Inc <> Date: Mon, 26 Apr 2010 18:40:54 +0000 (-0700) Subject: Change lib/file to use Posix_Getmntent_r for I18n and thread-safety. X-Git-Tag: 2010.04.25-253928~6 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f160849d8ef1ccfda3a45728d2d0ea3faf2d166e;p=thirdparty%2Fopen-vm-tools.git Change lib/file to use Posix_Getmntent_r for I18n and thread-safety. lib/file calls the thread-unsafe getmntent. It also ignores the local I18N encoding. Change it to call Posix_Getmntent_r, which takes care of both problems. On UTF-8 based systems, our Posix variant is defined to the underlying getmntent_r call, so check for cases where the supplied buffer is exhausted. Signed-off-by: Marcelo Vanzin --- diff --git a/open-vm-tools/lib/file/filePosix.c b/open-vm-tools/lib/file/filePosix.c index 4c1c120b2..3615e418b 100644 --- a/open-vm-tools/lib/file/filePosix.c +++ b/open-vm-tools/lib/file/filePosix.c @@ -1432,18 +1432,60 @@ FilePosixLookupMountPoint(char const *canPath, // IN: Canonical file path Bool *bind) // OUT: Mounted with --[r]bind? { FILE *f; - struct mntent *mnt; + struct mntent mnt; + char *buf; + size_t size; + size_t used; + char *ret = NULL; ASSERT(canPath); ASSERT(bind); + size = 4 * FILE_MAXPATH; // Should suffice for most locales + +retry: f = setmntent(MOUNTED, "r"); if (f == NULL) { return NULL; } - /* XXX getmntent() is not thread-safe. Use getmntent_r() instead. */ - while ((mnt = getmntent(f)) != NULL) { + buf = Util_SafeMalloc(size); + + while (Posix_Getmntent_r(f, &mnt, buf, size) != NULL) { + + /* + * Our Posix_Getmntent_r graciously sets errno when the buffer + * is too small, but on UTF-8 based platforms Posix_Getmntent_r + * is #defined to the system's getmntent_r, which can simply + * truncate the strings with no other indication. See how much + * space it used and increase the buffer size if needed. Note + * that if some of the strings are empty, they may share a + * common nul in the buffer, and the resulting size calculation + * will be a little over-zealous. + */ + + used = 0; + if (mnt.mnt_fsname) { + used += strlen(mnt.mnt_fsname) + 1; + } + if (mnt.mnt_dir) { + used += strlen(mnt.mnt_dir) + 1; + } + if (mnt.mnt_type) { + used += strlen(mnt.mnt_type) + 1; + } + if (mnt.mnt_opts) { + used += strlen(mnt.mnt_opts) + 1; + } + if (used >= size || !mnt.mnt_fsname || !mnt.mnt_dir || + !mnt.mnt_type || !mnt.mnt_opts) { + size += 4 * FILE_MAXPATH; + ASSERT(size <= 32 * FILE_MAXPATH); + free(buf); + endmntent(f); + goto retry; + } + /* * NB: A call to realpath is not needed as getmntent() already * returns it in canonical form. Additionally, it is bad @@ -1453,9 +1495,7 @@ FilePosixLookupMountPoint(char const *canPath, // IN: Canonical file path * all expecting. */ - if (strcmp(mnt->mnt_dir, canPath) == 0) { - endmntent(f); - + if (strcmp(mnt.mnt_dir, canPath) == 0) { /* * The --bind and --rbind options behave differently. See * FilePosixGetBlockDevice() for details. @@ -1465,16 +1505,20 @@ FilePosixLookupMountPoint(char const *canPath, // IN: Canonical file path * always "bind". */ - *bind = strstr(mnt->mnt_opts, "bind") != NULL; + *bind = strstr(mnt.mnt_opts, "bind") != NULL; + + ret = Util_SafeStrdup(mnt.mnt_fsname); - return Util_SafeStrdup(mnt->mnt_fsname); + break; } } // 'canPath' is not a mount point. endmntent(f); - return NULL; + free(buf); + + return ret; } #endif