]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Hold a reference to vSocket address family in vmtoolsd.
authorOliver Kurth <okurth@vmware.com>
Fri, 15 Sep 2017 18:22:52 +0000 (11:22 -0700)
committerOliver Kurth <okurth@vmware.com>
Fri, 15 Sep 2017 18:22:52 +0000 (11:22 -0700)
 On old hosts that do not support secure guestRpc vmtoolsd
 falls back to use backdoor. However, there could be vmci
 and vsocket drivers loaded in the guest that make vSocket
 consumers (e.g. guestLib and namespace-cmd) try vSocket
 all the time before falling back to backdoor. On old Linux
 guests like RHEL 5, 6 (kernels below 3.9 that do not have
 upstreamed vmci and vsocket drivers) this causes log spew
 in guest system logs because of vSocket address family being
 registered and unregistered on each RPC call (RpcChannel_SendOne).

 This could be solved in multiple ways involving some
 work from user. In order to solve this problem in a user
 friendly way, we hold a reference to vSocket device in
 vmtoolsd service, so that the reference goes away during
 Tools upgrade.

open-vm-tools/services/vmtoolsd/mainLoop.c
open-vm-tools/services/vmtoolsd/toolsCoreInt.h
open-vm-tools/services/vmtoolsd/toolsRpc.c

index e4c3a19dba66f2c47951a38139067bc0a293b34b..e541ab60e768e676359db162f57814c383de246c 100644 (file)
@@ -60,6 +60,9 @@ ToolsCoreCleanup(ToolsServiceState *state)
 {
    ToolsCorePool_Shutdown(&state->ctx);
    ToolsCore_UnloadPlugins(state);
+#if defined(__linux__)
+   ToolsCore_ReleaseVsockFamily(state);
+#endif
    if (state->ctx.rpc != NULL) {
       RpcChannel_Stop(state->ctx.rpc);
       RpcChannel_Destroy(state->ctx.rpc);
@@ -202,6 +205,15 @@ ToolsCoreRunLoop(ToolsServiceState *state)
       return 1;
    }
 
+#if defined(__linux__)
+   /*
+    * Init a reference to vSocket family.
+    */
+   if (!ToolsCore_InitVsockFamily(state)) {
+      return 1;
+   }
+#endif
+
    /*
     * The following criteria needs to hold for the main loop to be run:
     *
index 5c0f9e2d07bd8a4b1ed0513e1734dfaa26f3f7b9..096dcc3e5a179bb819f4b9e38c6b6ed06acdda1a 100644 (file)
@@ -86,6 +86,15 @@ typedef struct ToolsServiceState {
    RpcDebugLibData  *debugData;
    ToolsAppCtx    ctx;
    GArray        *providers;
+#if defined(__linux__)
+   /*
+    * We hold a reference to vSocket device to avoid
+    * address family re-registration when someone
+    * connects over vSocket.
+    */
+   int            vsockDev;
+   int            vsockFamily;
+#endif
 } ToolsServiceState;
 
 
@@ -112,6 +121,14 @@ ToolsCore_Setup(ToolsServiceState *state);
 gboolean
 ToolsCore_InitRpc(ToolsServiceState *state);
 
+#if defined(__linux__)
+gboolean
+ToolsCore_InitVsockFamily(ToolsServiceState *state);
+
+void
+ToolsCore_ReleaseVsockFamily(ToolsServiceState *state);
+#endif
+
 gboolean
 ToolsCore_LoadPlugins(ToolsServiceState *state);
 
index d078e3cd384a2d9e5e1e1495090c29c434fcd049..ad3542c843a9c4e61b211cc6619aa67e99432b40 100644 (file)
@@ -40,6 +40,9 @@
 #include "vmware/tools/utils.h"
 #include "vmware/tools/log.h"
 #include "vm_version.h"
+#if defined(__linux__)
+#include "vmci_sockets.h"
+#endif
 
 /**
  * Take action after an RPC channel reset.
@@ -58,6 +61,7 @@ ToolsCoreCheckReset(RpcChannel *chan,
    static gboolean version_sent = FALSE;
 
    ASSERT(state != NULL);
+   ASSERT(chan == state->ctx.rpc);
 
    if (success) {
       const gchar *app;
@@ -90,6 +94,13 @@ ToolsCoreCheckReset(RpcChannel *chan,
       g_signal_emit_by_name(state->ctx.serviceObj,
                             TOOLS_CORE_SIG_RESET,
                             &state->ctx);
+#if defined(__linux__)
+      /*
+       * Release the existing vSocket family.
+       */
+      ToolsCore_ReleaseVsockFamily(state);
+      ToolsCore_InitVsockFamily(state);
+#endif
    } else {
       VMTOOLSAPP_ERROR(&state->ctx, EXIT_FAILURE);
    }
@@ -394,3 +405,77 @@ ToolsCore_SetCapabilities(RpcChannel *chan,
       g_free(newcaps);
    }
 }
+
+
+#if defined(__linux__)
+/**
+ * Initializes the vSocket address family and sticks a reference
+ * to it in the service state.
+ *
+ * @param[in]  state    The service state.
+ *
+ * @return TRUE on success.
+ */
+
+gboolean
+ToolsCore_InitVsockFamily(ToolsServiceState *state)
+{
+   int vsockDev = -1;
+
+   ASSERT(state);
+   ASSERT(state->ctx.rpc);
+
+   state->vsockDev = -1;
+   state->vsockFamily = -1;
+
+   switch (RpcChannel_GetType(state->ctx.rpc)) {
+   case RPCCHANNEL_TYPE_INACTIVE:
+   case RPCCHANNEL_TYPE_PRIV_VSOCK:
+   case RPCCHANNEL_TYPE_UNPRIV_VSOCK:
+      return TRUE;
+   case RPCCHANNEL_TYPE_BKDOOR:
+      state->vsockFamily = VMCISock_GetAFValueFd(&vsockDev);
+      if (state->vsockFamily == -1) {
+         /*
+          * vSocket driver may not be loaded, log and continue.
+          */
+         g_warning("Couldn't get vSocket family.\n");
+         return TRUE;
+      }
+      ASSERT(vsockDev >= 0);
+      g_debug("Saving reference to vSocket device=%d, family=%d\n",
+              vsockDev, state->vsockFamily);
+      state->vsockDev = vsockDev;
+      return TRUE;
+   default:
+      NOT_IMPLEMENTED();
+   }
+
+   return FALSE;
+}
+
+
+/**
+ * Releases the reference to vSocket address family.
+ *
+ * @param[in]  state    The service state.
+ *
+ * @return TRUE on success.
+ */
+
+void
+ToolsCore_ReleaseVsockFamily(ToolsServiceState *state)
+{
+   ASSERT(state);
+   ASSERT(state->ctx.rpc);
+
+   if (state->vsockFamily >= 0) {
+      ASSERT(state->vsockDev >= 0);
+      g_debug("Releasing reference to vSocket device=%d, family=%d\n",
+              state->vsockDev, state->vsockFamily);
+      VMCISock_ReleaseAFValueFd(state->vsockDev);
+      state->vsockDev = -1;
+      state->vsockFamily = -1;
+   }
+}
+#endif