From: Oliver Kurth Date: Tue, 18 Dec 2018 21:19:47 +0000 (-0800) Subject: special case profile loading for StartProgram X-Git-Tag: stable-11.0.0~288 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f32fde16f226a67b42fe095aea33bf7b5e8040c0;p=thirdparty%2Fopen-vm-tools.git special case profile loading for StartProgram For StartProgram, we need to be sure there's no race in the profile unloading. So keep it open through the life of the started program. See related vgauth change. --- diff --git a/open-vm-tools/services/plugins/vix/vixTools.c b/open-vm-tools/services/plugins/vix/vixTools.c index 562233680..ec23f6323 100644 --- a/open-vm-tools/services/plugins/vix/vixTools.c +++ b/open-vm-tools/services/plugins/vix/vixTools.c @@ -293,10 +293,18 @@ typedef struct VixToolsRunProgramState { /* * State of a single asynch startProgram. + * + * On Windows, keep the user's token and profile HANDLEs around + * so the profile isn't unloaded until the program exits. */ typedef struct VixToolsStartProgramState { ProcMgr_AsyncProc *procState; +#if defined(_WIN32) && SUPPORT_VGAUTH + HANDLE hToken; + HANDLE hProfile; +#endif + void *eventQueue; } VixToolsStartProgramState; @@ -693,6 +701,10 @@ static Bool VixToolsCheckIfAuthenticationTypeEnabled(GKeyFile *confDictRef, VGAuthError TheVGAuthContext(VGAuthContext **ctx); +#ifdef _WIN32 +static void GuestAuthUnloadUserProfileAndToken(HANDLE hToken, HANDLE hProfile); +#endif + #endif @@ -1629,6 +1641,12 @@ VixToolsStartProgramImpl(const char *requestName, // IN Bool envBlockFromMalloc = TRUE; #endif GSource *timer; +#if defined(_WIN32) && SUPPORT_VGAUTH + HANDLE hToken = INVALID_HANDLE_VALUE; + HANDLE hProfile = INVALID_HANDLE_VALUE; + VGAuthError vgErr; + VGAuthContext *ctx; +#endif /* * Initialize this here so we can call free on its member variables in abort @@ -1788,6 +1806,42 @@ VixToolsStartProgramImpl(const char *requestName, // IN procArgs.envp = (char **)envVars; #endif +#if defined(_WIN32) && SUPPORT_VGAUTH + /* + * Special case profile handling for StartProgram. It should stay loaded + * until the program exits, so copy the profile and user handles for + * later cleanup, and clobber the profile handle so that it's not unloaded + * when the impersonation ends. + */ + if (GuestAuthEnabled()) { + asyncState->hToken = INVALID_HANDLE_VALUE; + asyncState->hProfile = INVALID_HANDLE_VALUE; + vgErr = TheVGAuthContext(&ctx); + if (VGAUTH_FAILED(vgErr)) { + err = VixToolsTranslateVGAuthError(vgErr); + g_warning("%s: Couldn't get the vgauth context\n", __FUNCTION__); + goto abort; + } + + vgErr = VGAuth_UserHandleAccessToken(ctx, currentUserHandle, &hToken); + if (VGAUTH_FAILED(vgErr)) { + err = VixToolsTranslateVGAuthError(vgErr); + g_warning("%s: Failed to get user token\n", __FUNCTION__); + goto abort; + } + vgErr = VGAuth_UserHandleGetUserProfile(ctx, currentUserHandle, + &hProfile); + if (VGAUTH_FAILED(vgErr)) { + err = VixToolsTranslateVGAuthError(vgErr); + g_warning("%s: Failed to get user profile\n", __FUNCTION__); + CloseHandle(hToken); + goto abort; + } + asyncState->hToken = hToken; + asyncState->hProfile = hProfile; + } +#endif + asyncState->procState = ProcMgr_ExecAsync(fullCommandLine, &procArgs); #if defined(_WIN32) @@ -1808,6 +1862,25 @@ VixToolsStartProgramImpl(const char *requestName, // IN g_debug("%s: started '%s', pid %"FMT64"d\n", __FUNCTION__, fullCommandLine, *pid); +#if defined(_WIN32) && SUPPORT_VGAUTH + /* + * Clobber the profile handle before un-impersonation. + */ + if (GuestAuthEnabled()) { + vgErr = VGAuth_UserHandleSetUserProfile(ctx, currentUserHandle, + INVALID_HANDLE_VALUE); + if (VGAUTH_FAILED(vgErr)) { + err = VixToolsTranslateVGAuthError(vgErr); + g_warning("%s: Failed to clobber user profile\n", __FUNCTION__); + // EndImpersonate will take care of profile, close hToken + CloseHandle(asyncState->hToken); + asyncState->hToken = INVALID_HANDLE_VALUE; + asyncState->hProfile = INVALID_HANDLE_VALUE; + goto abort; + } + } +#endif + /* * Start a periodic procedure to check the app periodically */ @@ -1823,6 +1896,7 @@ VixToolsStartProgramImpl(const char *requestName, // IN */ asyncState = NULL; + abort: free(tempCommandLine); free(fullCommandLine); @@ -2123,6 +2197,7 @@ done: * *----------------------------------------------------------------------------- */ + static void VixToolsUpdateStartedProgramList(VixToolsStartedProgramState *state) // IN { @@ -2147,6 +2222,9 @@ VixToolsUpdateStartedProgramList(VixToolsStartedProgramState *state) // I spList->endTime = state->endTime; spList->isRunning = FALSE; + g_debug("%s: started program '%s' has completed, exitCode %d\n", + __FUNCTION__, spList->fullCommandLine, spList->exitCode); + /* * Don't let the procState be free'd on Windows to * keep OS from reusing the pid. We need to free @@ -8192,6 +8270,16 @@ VixToolsFreeStartProgramState(VixToolsStartProgramState *asyncState) // IN if (NULL == asyncState) { return; } +#if defined(_WIN32) && SUPPORT_VGAUTH + /* + * Unload the user profile if saved. + */ + if (asyncState->hProfile != INVALID_HANDLE_VALUE && + asyncState->hToken != INVALID_HANDLE_VALUE) { + GuestAuthUnloadUserProfileAndToken(asyncState->hToken, + asyncState->hProfile); + } +#endif free(asyncState); } // VixToolsFreeStartProgramState @@ -11854,4 +11942,41 @@ TheVGAuthContext(VGAuthContext **ctx) // OUT *ctx = vgaCtx; return vgaCode; } -#endif + + +#ifdef _WIN32 +/* + *----------------------------------------------------------------------------- + * + * GuestAuthUnloadUserProfileAndToken -- + * + * Unload user profile and close user token. + * + * Helper to handle StartProgram cleanup. + * + * Return value: + * None + * + * Side effects: + * None + * + *----------------------------------------------------------------------------- + */ + +static void +GuestAuthUnloadUserProfileAndToken(HANDLE hToken, + HANDLE hProfile) +{ + if (GuestAuthEnabled()) { + g_debug("%s: special-case profile unload %p\n", __FUNCTION__, hProfile); + if (!UnloadUserProfile(hToken, hProfile)) { + g_warning("%s: UnloadUserProfile() failed %d\n", + __FUNCTION__, GetLastError()); + } + CloseHandle(hToken); + } +} +#endif // _WIN32 + +#endif // SUPPORT_VGAUTH +