Fix procMgr library for Windows.
- For windows, to retrieve the command line for a target process,
the procMgr library creates a remote thread in the target process
and executes GetCommandLine function. This approach is OK. But for
few applications that are not built with proper flags, creating a
remote thread may crash the application. In order to avoid any
issues, it was decided not use the 'remote thread' approach by DEFAULT.
- Refactored the procMgr APIs to take an input argument from the
user if the 'remote thread' approach needs to be used.
- Refactored the procMgr APIs to conditionally use the WMI for
retrieving the command line for a target process.
- New options are provided to the user if the 'remote thread'
and 'WMI' approaches need to be forced. Modified the VIX tools plugin
to read and honor the new flags from tools.conf
The following are the new flags under guestoperations group.
useRemoteThreadForProcessCommandLine
useWMIForProcessCommandLine
The default value for the above new flags is false. User can set them
to true if needed.
- Re-factored some code in appInfo plugin that calls procMgr library.
The appinfo plugin doesn't really use the commandline. So, modified the
appinfo plugin to just use the API that doesn't use the complicated
approaches for the listing down the processes.
/*********************************************************
- * Copyright (C) 2002-2019 VMware, Inc. All rights reserved.
+ * Copyright (C) 2002-2020 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
ProcMgrProcInfoArray *ProcMgr_ListProcesses(void);
#if defined(_WIN32)
-ProcMgrProcInfoArray *ProcMgr_ListProcessesEx(void);
+ProcMgrProcInfoArray *ProcMgr_ListProcessesEx(Bool useRemoteThreadForCmdLine,
+ Bool useWMIForCmdLine);
#endif
void ProcMgr_FreeProcList(ProcMgrProcInfoArray *procList);
/*********************************************************
- * Copyright (C) 2019 VMware, Inc. All rights reserved.
+ * Copyright (C) 2019-2020 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
}
+/*
+ *----------------------------------------------------------------------
+ * AppInfo_GetAppList --
+ *
+ * Generates the application information list.
+ *
+ * @retval Pointer to the newly allocated application list. The caller must
+ * free the memory using AppInfoDestroyAppList function.
+ * NULL if any error occurs.
+ *
+ *----------------------------------------------------------------------
+ */
+
+GSList *
+AppInfo_GetAppList(void) {
+ GSList *appList = NULL;
+ int i;
+ ProcMgrProcInfoArray *procList = NULL;
+ size_t procCount;
+
+ procList = ProcMgr_ListProcesses();
+
+ if (procList == NULL) {
+ g_warning("Failed to get the list of processes.\n");
+ return appList;
+ }
+
+ procCount = ProcMgrProcInfoArray_Count(procList);
+ for (i = 0; i < procCount; i++) {
+ AppInfo *appInfo;
+ ProcMgrProcInfo *procInfo = ProcMgrProcInfoArray_AddressOf(procList, i);
+ appInfo = AppInfoGetAppInfo(procInfo);
+ if (NULL != appInfo) {
+ appList = g_slist_prepend(appList, appInfo);
+ }
+ }
+
+ ProcMgr_FreeProcList(procList);
+
+ return appList;
+}
+
+
/*
*****************************************************************************
* AppInfoGatherTask --
/*********************************************************
- * Copyright (C) 2019 VMware, Inc. All rights reserved.
+ * Copyright (C) 2019-2020 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
#include "vm_basic_types.h"
#include <glib.h>
#include "vmware/tools/plugin.h"
+#include "procMgr.h"
#if defined(_WIN32)
GSList *AppInfo_SortAppList(GSList *appList);
void AppInfo_DestroyAppList(GSList *appList);
+
+AppInfo *AppInfoGetAppInfo(ProcMgrProcInfo *procInfo);
+
#endif /* _APPINFOINT_H_ */
/*********************************************************
- * Copyright (C) 2019 VMware, Inc. All rights reserved.
+ * Copyright (C) 2019-2020 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
# error This file should not be compiled.
#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
#include "appInfoInt.h"
-#include "procMgr.h"
-#include "vmware.h"
-#include "str.h"
#include "util.h"
return appInfo;
}
-
-
-/*
- *----------------------------------------------------------------------
- * AppInfo_GetAppList --
- *
- * Generates the application information list.
- *
- * @retval Pointer to the newly allocated application list. The caller must
- * free the memory using AppInfoDestroyAppList function.
- * NULL if any error occurs.
- *
- *----------------------------------------------------------------------
- */
-
-GSList *
-AppInfo_GetAppList(void) {
- GSList *appList = NULL;
- int i;
- ProcMgrProcInfoArray *procList = NULL;
- size_t procCount;
-
-#if defined(_WIN32)
- procList = ProcMgr_ListProcessesEx();
-#else
- procList = ProcMgr_ListProcesses();
-#endif
-
- if (procList == NULL) {
- g_warning("Failed to get the list of processes.\n");
- return appList;
- }
-
- procCount = ProcMgrProcInfoArray_Count(procList);
- for (i = 0; i < procCount; i++) {
- AppInfo *appInfo;
- ProcMgrProcInfo *procInfo = ProcMgrProcInfoArray_AddressOf(procList, i);
- appInfo = AppInfoGetAppInfo(procInfo);
- if (NULL != appInfo) {
- appList = g_slist_prepend(appList, appInfo);
- }
- }
-
- ProcMgr_FreeProcList(procList);
-
- return appList;
-}
static gboolean gSupportVGAuth = USE_VGAUTH_DEFAULT;
static gboolean QueryVGAuthConfig(GKeyFile *confDictRef);
+#ifdef _WIN32
+/*
+ * Check bug 2508431 for more details. If an application is not built
+ * with proper flags, 'creating a remote thread' to get the process
+ * command line will crash the target process. To avoid any such crash,
+ * 'remote thread' approach is not used by default.
+ *
+ * But 'remote thread' approach can be turned on (for whatever reason)
+ * by setting the following option to true in the tools.conf file.
+ *
+ * For few processes, 'WMI' can provide detailed commandline information.
+ * But using 'WMI' is a heavy weight approach and may affect the CPU
+ * performance and hence it is disabled by default. It can always be
+ * turned on by a setting (as mentioned below) in the tools.conf file.
+ */
+#define VIXTOOLS_CONFIG_USE_REMOTE_THREAD_PROCESS_COMMAND_LINE \
+ "useRemoteThreadForProcessCommandLine"
+
+#define VIXTOOLS_CONFIG_USE_WMI_PROCESS_COMMAND_LINE \
+ "useWMIForProcessCommandLine"
+
+#define USE_REMOTE_THREAD_PROCESS_COMMAND_LINE_DEFAULT FALSE
+#define USE_WMI_PROCESS_COMMAND_LINE_DEFAULT FALSE
+
+#endif
+
#if ALLOW_LOCAL_SYSTEM_IMPERSONATION_BYPASS
static gchar *gCurrentUsername = NULL;
*-----------------------------------------------------------------------------
*/
-VixError
+static VixError
VixToolsListProcessesExGenerateData(uint32 numPids, // IN
const uint64 *pids, // IN
+ GKeyFile *confDictRef, // IN
size_t *resultSize, // OUT
char **resultBuffer) // OUT
{
Bool bRet;
size_t procCount;
+#ifdef _WIN32
+ gboolean useRemoteThreadProcCmdLine;
+ gboolean useWMIProcCmdLine;
+#endif
+
DynBuf_Init(&dynBuffer);
/*
* return an error code so there's no risk of errno/LastError
* being clobbered.
*/
+#ifdef _WIN32
+ useRemoteThreadProcCmdLine = VixTools_ConfigGetBoolean(confDictRef,
+ VIX_TOOLS_CONFIG_API_GROUPNAME,
+ VIXTOOLS_CONFIG_USE_REMOTE_THREAD_PROCESS_COMMAND_LINE,
+ USE_REMOTE_THREAD_PROCESS_COMMAND_LINE_DEFAULT);
+
+ useWMIProcCmdLine = VixTools_ConfigGetBoolean(confDictRef,
+ VIX_TOOLS_CONFIG_API_GROUPNAME,
+ VIXTOOLS_CONFIG_USE_WMI_PROCESS_COMMAND_LINE,
+ USE_WMI_PROCESS_COMMAND_LINE_DEFAULT);
+
+ g_debug("Options for process cmdline: useRemoeThread: %d, useWMI: %d\n",
+ useRemoteThreadProcCmdLine, useWMIProcCmdLine);
+
+ procList = ProcMgr_ListProcessesEx(useRemoteThreadProcCmdLine,
+ useWMIProcCmdLine);
+#else
procList = ProcMgr_ListProcesses();
+#endif
if (NULL == procList) {
err = FoundryToolsDaemon_TranslateSystemErr();
goto abort;
*-----------------------------------------------------------------------------
*/
-VixError
+static VixError
VixToolsListProcessesEx(VixCommandRequestHeader *requestMsg, // IN
size_t maxBufferSize, // IN
+ GKeyFile *confDictRef, // IN
void *eventQueue, // IN
char **result) // OUT
{
pids = (uint64 *)((char *)requestMsg + sizeof(*listRequest));
}
- err = VixToolsListProcessesExGenerateData(numPids, pids,
+ err = VixToolsListProcessesExGenerateData(numPids, pids, confDictRef,
&fullResultSize,
&fullResultBuffer);
////////////////////////////////////
case VIX_COMMAND_LIST_PROCESSES_EX:
err = VixToolsListProcessesEx(requestMsg,
- maxResultBufferSize,
- eventQueue,
- &resultValue);
+ maxResultBufferSize,
+ confDictRef,
+ eventQueue,
+ &resultValue);
deleteResultValue = TRUE;
break;