From: Oliver Kurth Date: Fri, 15 Sep 2017 18:22:52 +0000 (-0700) Subject: Hold a reference to vSocket address family in vmtoolsd. X-Git-Tag: stable-10.2.0~643 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7b8be4232011660d2fda9964815cfa2fed2f1978;p=thirdparty%2Fopen-vm-tools.git Hold a reference to vSocket address family in vmtoolsd. 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. --- diff --git a/open-vm-tools/services/vmtoolsd/mainLoop.c b/open-vm-tools/services/vmtoolsd/mainLoop.c index e4c3a19db..e541ab60e 100644 --- a/open-vm-tools/services/vmtoolsd/mainLoop.c +++ b/open-vm-tools/services/vmtoolsd/mainLoop.c @@ -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: * diff --git a/open-vm-tools/services/vmtoolsd/toolsCoreInt.h b/open-vm-tools/services/vmtoolsd/toolsCoreInt.h index 5c0f9e2d0..096dcc3e5 100644 --- a/open-vm-tools/services/vmtoolsd/toolsCoreInt.h +++ b/open-vm-tools/services/vmtoolsd/toolsCoreInt.h @@ -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); diff --git a/open-vm-tools/services/vmtoolsd/toolsRpc.c b/open-vm-tools/services/vmtoolsd/toolsRpc.c index d078e3cd3..ad3542c84 100644 --- a/open-vm-tools/services/vmtoolsd/toolsRpc.c +++ b/open-vm-tools/services/vmtoolsd/toolsRpc.c @@ -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