VBoxServiceControlSession.cpp revision 026b1e278173a87acfffc3dd69c71766b7259b5e
65fea56f17cd614bc8908264df980a62e1931468vboxsync * VBoxServiceControlSession - Guest session handling. Also handles
65fea56f17cd614bc8908264df980a62e1931468vboxsync * the forked session processes.
65fea56f17cd614bc8908264df980a62e1931468vboxsync * Copyright (C) 2013-2014 Oracle Corporation
65fea56f17cd614bc8908264df980a62e1931468vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
65fea56f17cd614bc8908264df980a62e1931468vboxsync * available from http://www.virtualbox.org. This file is free software;
65fea56f17cd614bc8908264df980a62e1931468vboxsync * you can redistribute it and/or modify it under the terms of the GNU
65fea56f17cd614bc8908264df980a62e1931468vboxsync * General Public License (GPL) as published by the Free Software
65fea56f17cd614bc8908264df980a62e1931468vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
65fea56f17cd614bc8908264df980a62e1931468vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
65fea56f17cd614bc8908264df980a62e1931468vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
65fea56f17cd614bc8908264df980a62e1931468vboxsync/*******************************************************************************
65fea56f17cd614bc8908264df980a62e1931468vboxsync* Header Files *
65fea56f17cd614bc8908264df980a62e1931468vboxsync*******************************************************************************/
65fea56f17cd614bc8908264df980a62e1931468vboxsyncusing namespace guestControl;
65fea56f17cd614bc8908264df980a62e1931468vboxsync/*******************************************************************************
65fea56f17cd614bc8908264df980a62e1931468vboxsync* Externals *
65fea56f17cd614bc8908264df980a62e1931468vboxsync*******************************************************************************/
65fea56f17cd614bc8908264df980a62e1931468vboxsyncextern int VBoxServiceLogCreate(const char *pszLogFile);
65fea56f17cd614bc8908264df980a62e1931468vboxsyncextern void VBoxServiceLogDestroy(void);
65fea56f17cd614bc8908264df980a62e1931468vboxsync/*******************************************************************************
65fea56f17cd614bc8908264df980a62e1931468vboxsync* Internal Functions *
65fea56f17cd614bc8908264df980a62e1931468vboxsync*******************************************************************************/
65fea56f17cd614bc8908264df980a62e1931468vboxsyncstatic int gstcntlSessionFileDestroy(PVBOXSERVICECTRLFILE pFile);
65fea56f17cd614bc8908264df980a62e1931468vboxsyncstatic int gstcntlSessionFileAdd(PVBOXSERVICECTRLSESSION pSession, PVBOXSERVICECTRLFILE pFile);
65fea56f17cd614bc8908264df980a62e1931468vboxsyncstatic PVBOXSERVICECTRLFILE gstcntlSessionFileGetLocked(const PVBOXSERVICECTRLSESSION pSession, uint32_t uHandle);
65fea56f17cd614bc8908264df980a62e1931468vboxsyncstatic DECLCALLBACK(int) gstcntlSessionThread(RTTHREAD ThreadSelf, void *pvUser);
65fea56f17cd614bc8908264df980a62e1931468vboxsync/* Host -> Guest handlers. */
65fea56f17cd614bc8908264df980a62e1931468vboxsyncstatic int gstcntlSessionHandleDirRemove(PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx);
65fea56f17cd614bc8908264df980a62e1931468vboxsyncstatic int gstcntlSessionHandleFileOpen(PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx);
65fea56f17cd614bc8908264df980a62e1931468vboxsyncstatic int gstcntlSessionHandleFileClose(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx);
65fea56f17cd614bc8908264df980a62e1931468vboxsyncstatic int gstcntlSessionHandleFileRead(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx);
65fea56f17cd614bc8908264df980a62e1931468vboxsyncstatic int gstcntlSessionHandleFileWrite(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx, void *pvScratchBuf, size_t cbScratchBuf);
65fea56f17cd614bc8908264df980a62e1931468vboxsyncstatic int gstcntlSessionHandleFileSeek(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx);
65fea56f17cd614bc8908264df980a62e1931468vboxsyncstatic int gstcntlSessionHandleFileTell(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx);
65fea56f17cd614bc8908264df980a62e1931468vboxsyncstatic int gstcntlSessionHandlePathRename(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx);
65fea56f17cd614bc8908264df980a62e1931468vboxsyncstatic int gstcntlSessionHandleProcExec(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx);
65fea56f17cd614bc8908264df980a62e1931468vboxsyncstatic int gstcntlSessionHandleProcInput(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx, void *pvScratchBuf, size_t cbScratchBuf);
65fea56f17cd614bc8908264df980a62e1931468vboxsyncstatic int gstcntlSessionHandleProcOutput(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx);
65fea56f17cd614bc8908264df980a62e1931468vboxsyncstatic int gstcntlSessionHandleProcTerminate(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx);
65fea56f17cd614bc8908264df980a62e1931468vboxsyncstatic int gstcntlSessionHandleProcWaitFor(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx);
65fea56f17cd614bc8908264df980a62e1931468vboxsync/** Generic option indices for session fork arguments. */
65fea56f17cd614bc8908264df980a62e1931468vboxsync VBOXSERVICESESSIONOPT_FIRST = 1000, /* For initialization. */
65fea56f17cd614bc8908264df980a62e1931468vboxsyncstatic int gstcntlSessionFileDestroy(PVBOXSERVICECTRLFILE pFile)
65fea56f17cd614bc8908264df980a62e1931468vboxsync /* Remove file entry in any case. */
65fea56f17cd614bc8908264df980a62e1931468vboxsync /* Destroy this object. */
65fea56f17cd614bc8908264df980a62e1931468vboxsync/** @todo No locking done yet! */
65fea56f17cd614bc8908264df980a62e1931468vboxsyncstatic PVBOXSERVICECTRLFILE gstcntlSessionFileGetLocked(const PVBOXSERVICECTRLSESSION pSession,
65fea56f17cd614bc8908264df980a62e1931468vboxsync /** @todo Use a map later! */
65fea56f17cd614bc8908264df980a62e1931468vboxsync RTListForEach(&pSession->lstFiles, pFileCur, VBOXSERVICECTRLFILE, Node)
65fea56f17cd614bc8908264df980a62e1931468vboxsyncstatic int gstcntlSessionHandleDirRemove(PVBOXSERVICECTRLSESSION pSession,
65fea56f17cd614bc8908264df980a62e1931468vboxsync /* Directory to remove. */
65fea56f17cd614bc8908264df980a62e1931468vboxsync /* Flags of type DIRREMOVE_FLAG_. */
65fea56f17cd614bc8908264df980a62e1931468vboxsync bool fRecursive = false;
fRecursive = true;
if (fRecursive)
#ifdef DEBUG
return rc;
&uOffset);
VBoxServiceVerbose(4, "[File %s]: szAccess=%s, szDisposition=%s, szSharing=%s, uOffset=%RU64, rc=%Rrc\n",
if (pFile)
&& uOffset)
#ifdef DEBUG
VBoxServiceVerbose(4, "Opening file \"%s\" (open mode=\"%s\", disposition=\"%s\", creation mode=0x%x returned rc=%Rrc\n",
return rc;
if (pFile)
#ifdef DEBUG
return rc;
if (pFile)
if (cbToRead)
if (!pvDataRead)
&& pvDataRead)
#ifdef DEBUG
return rc;
if (pFile)
if (cbToRead)
if (!pvDataRead)
&& pvDataRead)
#ifdef DEBUG
return rc;
&cbToWrite);
if (pFile)
#ifdef DEBUG
VBoxServiceVerbose(4, "[File %s]: Writing pvScratchBuf=%p, cbToWrite=%RU32, cbWritten=%zu, rc=%Rrc\n",
#ifdef DEBUG
return rc;
if (pFile)
#ifdef DEBUG
VBoxServiceVerbose(4, "[File %s]: Writing iOffset=%RI64, pvScratchBuf=%p, cbToWrite=%RU32, cbWritten=%zu, rc=%Rrc\n",
#ifdef DEBUG
return rc;
if (pFile)
unsigned uSeekMethodIPRT;
switch (uSeekMethod)
case GUEST_FILE_SEEKTYPE_END:
#ifdef DEBUG
#ifdef DEBUG
return rc;
if (pFile)
#ifdef DEBUG
#ifdef DEBUG
return rc;
&uFlags);
#ifdef DEBUG
return rc;
VBoxServiceVerbose(3, "Request to start process szCmd=%s, uFlags=0x%x, szArgs=%s, szEnv=%s, uTimeout=%RU32\n",
if (fStartAllowed)
return rc;
VBoxServiceError("Too much process input received, rejecting: uPID=%RU32, cbSize=%RU32, cbScratchBuf=%RU32\n",
bool fPendingClose = false;
fPendingClose = true;
#ifdef DEBUG
if (pProcess)
#ifdef DEBUG
return rc;
#ifdef DEBUG_andy
if (pProcess)
#ifdef DEBUG_andy
return rc;
if (pProcess)
#ifdef DEBUG_andy
return rc;
if (pProcess)
return rc;
volatile bool *pfShutdown)
switch (uMsg)
case HOST_SESSION_CLOSE:
case HOST_DIR_REMOVE:
case HOST_EXEC_CMD:
case HOST_EXEC_SET_INPUT:
case HOST_EXEC_GET_OUTPUT:
case HOST_EXEC_TERMINATE:
case HOST_EXEC_WAIT_FOR:
case HOST_FILE_OPEN:
case HOST_FILE_CLOSE:
case HOST_FILE_READ:
case HOST_FILE_READ_AT:
case HOST_FILE_WRITE:
case HOST_FILE_WRITE_AT:
case HOST_FILE_SEEK:
case HOST_FILE_TELL:
case HOST_PATH_RENAME:
return rc;
return rc;
bool fProcessAlive = true;
int rcWait;
fProcessAlive = false;
if (!u64TimeoutStart)
VBoxServiceVerbose(3, "Guest session ID=%RU32 thread was asked to terminate, waiting for session process to exit (%RU32ms timeout) ...\n",
if (!fProcessAlive)
VBoxServiceVerbose(2, "Guest session process (ID=%RU32) terminated with rc=%Rrc, reason=%ld, status=%d\n",
VBoxServiceError("- Is logging enabled and the output directory is read-only by the guest session user?\n");
if (fProcessAlive)
case RTPROCEXITREASON_NORMAL:
case RTPROCEXITREASON_ABEND:
case RTPROCEXITREASON_SIGNAL:
VBoxServiceVerbose(3, "Guest session ID=%RU32 thread ended with sessionStatus=%RU32, sessionRc=%Rrc\n",
return rc;
bool fSessionFilter = true;
fSessionFilter = false;
VBGLR3GUESTCTRLCMDCTX ctx = { uClientID, VBOX_GUESTCTRL_CONTEXTID_MAKE_SESSION(pSession->StartupInfo.uSessionID) };
if (!pvScratchBuf)
bool fShutdown = false;
#ifdef DEBUG
VBoxServiceVerbose(4, "Message requires %RU32 parameters, but only 2 supplied -- retrying request (no error!)...\n", cParms);
VBoxServiceVerbose(3, "Getting host message failed with %Rrc\n", rc); /* VERR_GEN_IO_FAILURE seems to be normal if ran into timeout. */
if (fShutdown)
if (pvScratchBuf)
if (uClientID)
PVBOXSERVICECTRLPROCESS GstCntlSessionRetainProcess(PVBOXSERVICECTRLSESSION pSession, uint32_t uPID)
return pProcess;
cProcesses++;
while (pProcess)
if (fLast)
#ifdef DEBUG
while (pProcess)
if (fLast)
while (pFile)
if (fLast)
return rc;
return rc;
return rc;
return VINF_SUCCESS;
return VINF_SUCCESS;
bool *pbAllowed)
bool fLimitReached = false;
if (iProcsLeft < 0)
fLimitReached = true;
return rc;
#ifdef DEBUG
return VERR_ALREADY_EXISTS;
if (pSessionThread)
sizeof(VBOXSERVICECTRLSESSIONSTARTUPINFO));
if (fAnonymous)
VBoxServiceVerbose(3, "New anonymous guest session ID=%RU32 created, uFlags=%x, using protocol %RU32\n",
VBoxServiceVerbose(3, "Forking new guest session ID=%RU32, szUser=%s, szPassword=%s, szDomain=%s, uFlags=%x, using protocol %RU32\n",
#ifdef DEBUG
if (pszExeName)
if (!fAnonymous)
if (!RTStrPrintf(szParmUserName, sizeof(szParmUserName), "--user=%s", pSessionThread->StartupInfo.szUser))
if (RT_SUCCESS(rc) && !RTStrPrintf(szParmSessionProto, sizeof(szParmSessionProto), "--session-proto=%RU32",
#ifdef DEBUG
#ifdef DEBUG
if (!fAnonymous)
if (pszLogFile)
char *pszLogNewSuffix;
#ifndef DEBUG
if (pszLogSuff)
#ifdef DEBUG
iOptIdx = 0;
return rc;
pThread));
return VERR_NOT_FOUND;
int rcThread;
return rc;
return rc;
while (pSessionThread)
if (fLast)
return rc;
#ifdef DEBUG
#ifdef DEBUG
int ch;
switch (ch)
#ifdef DEBUG
#ifdef DEBUG
g_cVerbosity++;
case VINF_GETOPT_NOT_OPTION:
return rcExit;