]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Improvements for ProcMgr library.
authorOliver Kurth <okurth@vmware.com>
Mon, 17 Jun 2019 18:41:36 +0000 (11:41 -0700)
committerOliver Kurth <okurth@vmware.com>
Mon, 17 Jun 2019 18:41:36 +0000 (11:41 -0700)
* This changeset fixes various issues related to ProcMgr library.

== Retrieve the absolute path of the image for each process ==
* When listing down the processes, it is useful to retrieve the
  absolute path of the process binary.

=== For Linux ===:
* In /proc filesystem, /proc/{PID}/exe is a symlink to the binary
  and we can make use of it to figure out the absolute path.

* If /proc/{PID}/exe is not a valid symlink, then the 'cmdline'
  is parsed and aboslute path is calculated accordingly.

* Note: This changeset tries its best to figure out the absolute path.
  If it can't, then the attribute is set to NULL.

== Misc issues fixed. ==
=== Linux ===
* Fixed a memory leak with 'procCmdName' while looping through the
  /proc/ directory entries.

* Fixed another memory leak with cmdLineTemp and cmdStatTemp variables
  while listing down the processes in linux guests.

* In few cases, /proc/{PID}/cmdline file contains multiple NUL
  characters at the end.  In that case, the existing code converts them
  into 'whitespaces'. Fixed the code to chop of all the trailing
  whitespaces in the command line.

open-vm-tools/lib/include/procMgr.h
open-vm-tools/lib/procMgr/procMgrPosix.c

index e6c0a62eccb3718f4fd7cacb05e6351f0623c179..d6adad1ba86f014eb0cf79ebfa5c4a19b1cf0074 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************
- * Copyright (C) 2002-2017 VMware, Inc. All rights reserved.
+ * Copyright (C) 2002-2019 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
@@ -56,6 +56,9 @@ typedef struct ProcMgr_AsyncProc ProcMgr_AsyncProc;
 typedef struct ProcMgrProcInfo {
    ProcMgr_Pid procId;
    char *procCmdName;             // UTF-8
+#if defined(__linux__) || defined(_WIN32)
+   char *procCmdAbsPath;          // UTF-8
+#endif
    char *procCmdLine;             // UTF-8
    char *procOwner;               // UTF-8
 #if defined(_WIN32)
@@ -134,6 +137,11 @@ typedef int Selectable;
 #endif
 
 ProcMgrProcInfoArray *ProcMgr_ListProcesses(void);
+
+#if defined(_WIN32)
+ProcMgrProcInfoArray *ProcMgr_ListProcessesEx(void);
+#endif
+
 void ProcMgr_FreeProcList(ProcMgrProcInfoArray *procList);
 Bool ProcMgr_KillByPid(ProcMgr_Pid procId);
 
index 97c995900f54ec4f545c94dc25386ca11569b1ef..e2cd0619f0e22db2d1df7683c48221581da4a1d4 100644 (file)
@@ -258,6 +258,7 @@ ProcMgr_ListProcesses(void)
    procList = Util_SafeCalloc(1, sizeof *procList);
    ProcMgrProcInfoArray_Init(procList, 0);
    procInfo.procCmdName = NULL;
+   procInfo.procCmdAbsPath = NULL;
    procInfo.procCmdLine = NULL;
    procInfo.procOwner = NULL;
 
@@ -386,6 +387,21 @@ ProcMgr_ListProcesses(void)
          continue;
       }
 
+      if (snprintf(cmdFilePath,
+                   sizeof cmdFilePath,
+                   "/proc/%s/exe",
+                   ent->d_name) != -1) {
+         int exeLen;
+         char exeRealPath[1024];
+
+         exeLen = readlink(cmdFilePath, exeRealPath, sizeof exeRealPath -1);
+         if (exeLen != -1) {
+            exeRealPath[exeLen] = '\0';
+            procInfo.procCmdAbsPath =
+               Unicode_Alloc(exeRealPath, STRING_ENCODING_DEFAULT);
+         }
+      }
+
       if (numRead > 0) {
          for (replaceLoop = 0 ; replaceLoop < numRead ; replaceLoop++) {
             if ('\0' == cmdLineTemp[replaceLoop]) {
@@ -405,6 +421,11 @@ ProcMgr_ListProcesses(void)
                      cmdNameBegin++;
                   }
                   procInfo.procCmdName = Unicode_Alloc(cmdNameBegin, STRING_ENCODING_DEFAULT);
+                  if (procInfo.procCmdAbsPath != NULL &&
+                      cmdLineTemp[0] == '/') {
+                     procInfo.procCmdAbsPath =
+                        Unicode_Alloc(cmdLineTemp, STRING_ENCODING_DEFAULT);
+                  }
                   cmdNameLookup = FALSE;
                }
 
@@ -470,6 +491,10 @@ ProcMgr_ListProcesses(void)
              * Store the command name.
              */
             procInfo.procCmdName = Unicode_Alloc(cmdLineTemp, STRING_ENCODING_DEFAULT);
+            if (procInfo.procCmdAbsPath != NULL &&
+                cmdLineTemp[0] == '/') {
+               procInfo.procCmdAbsPath = Unicode_Alloc(cmdLineTemp, STRING_ENCODING_DEFAULT);
+            }
          }
       }
 
@@ -543,6 +568,17 @@ ProcMgr_ListProcesses(void)
        * Store the command line string pointer in dynbuf.
        */
       if (cmdLineTemp) {
+         int i;
+
+         /*
+          * Chop off the trailing whitespace characters.
+          */
+         for (i = strlen(cmdLineTemp) - 1 ;
+              i >= 0 && cmdLineTemp[i] == ' ' ;
+              i--) {
+            cmdLineTemp[i] = '\0';
+         }
+
          procInfo.procCmdLine = Unicode_Alloc(cmdLineTemp, STRING_ENCODING_DEFAULT);
       } else {
          procInfo.procCmdLine = Unicode_Alloc("", STRING_ENCODING_UTF8);
@@ -572,13 +608,21 @@ ProcMgr_ListProcesses(void)
       if (!ProcMgrProcInfoArray_Push(procList, procInfo)) {
          Warning("%s: failed to expand DynArray - out of memory\n",
                  __FUNCTION__);
+         free(cmdLineTemp);
+         free(cmdStatTemp);
          goto abort;
       }
       procInfo.procCmdName = NULL;
+      procInfo.procCmdAbsPath = NULL;
       procInfo.procCmdLine = NULL;
       procInfo.procOwner = NULL;
 
 next_entry:
+      free(procInfo.procCmdName);
+      procInfo.procCmdName = NULL;
+      free(procInfo.procCmdAbsPath);
+      procInfo.procCmdAbsPath = NULL;
+
       free(cmdLineTemp);
       free(cmdStatTemp);
    } // while readdir
@@ -591,6 +635,7 @@ abort:
    closedir(dir);
 
    free(procInfo.procCmdName);
+   free(procInfo.procCmdAbsPath);
    free(procInfo.procCmdLine);
    free(procInfo.procOwner);
 
@@ -1195,6 +1240,9 @@ ProcMgr_FreeProcList(ProcMgrProcInfoArray *procList)
    for (i = 0; i < procCount; i++) {
       ProcMgrProcInfo *procInfo = ProcMgrProcInfoArray_AddressOf(procList, i);
       free(procInfo->procCmdName);
+#if defined(__linux__)
+      free(procInfo->procCmdAbsPath);
+#endif
       free(procInfo->procCmdLine);
       free(procInfo->procOwner);
    }