From: VMware, Inc <> Date: Mon, 20 Dec 2010 21:53:12 +0000 (-0800) Subject: Internal branch sync. Included in this change: X-Git-Tag: 2010.12.19-339835~48 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5aec778c91cdb5b13b1f44f1a236e3ebc9bca462;p=thirdparty%2Fopen-vm-tools.git Internal branch sync. Included in this change: . VIX: try to use bash for starting processes on Solaris. . VIX: escaping strings in XML VMAutomation responses. . vmxnet: allow changing MAC address in FreeBSD. . changes in shared code that don't affect open-vm-tools functionality. Signed-off-by: Marcelo Vanzin --- diff --git a/open-vm-tools/lib/foundryMsg/foundryMsg.c b/open-vm-tools/lib/foundryMsg/foundryMsg.c index 56930a26c..8965b45a6 100644 --- a/open-vm-tools/lib/foundryMsg/foundryMsg.c +++ b/open-vm-tools/lib/foundryMsg/foundryMsg.c @@ -133,10 +133,8 @@ static const VixCommandInfo vixCommandInfoTable[] = { VIX_COMMAND_CATEGORY_PRIVILEGED), VIX_DEFINE_COMMAND_INFO(VIX_COMMAND_DELETE_VM, VIX_COMMAND_CATEGORY_PRIVILEGED), - VIX_DEFINE_COMMAND_INFO(VIX_COMMAND_SYNCDRIVER_FREEZE, - VIX_COMMAND_CATEGORY_ALWAYS_ALLOWED), - VIX_DEFINE_COMMAND_INFO(VIX_COMMAND_SYNCDRIVER_THAW, - VIX_COMMAND_CATEGORY_ALWAYS_ALLOWED), + VIX_DEFINE_UNUSED_COMMAND, + VIX_DEFINE_UNUSED_COMMAND, VIX_DEFINE_UNUSED_COMMAND, VIX_DEFINE_UNUSED_COMMAND, VIX_DEFINE_COMMAND_INFO(VIX_COMMAND_SET_GUEST_PRINTER, diff --git a/open-vm-tools/lib/include/vixCommands.h b/open-vm-tools/lib/include/vixCommands.h index cb40ffaa5..c6551cfa3 100644 --- a/open-vm-tools/lib/include/vixCommands.h +++ b/open-vm-tools/lib/include/vixCommands.h @@ -98,6 +98,7 @@ enum { VIX_REQUESTMSG_REQUIRES_INTERACTIVE_ENVIRONMENT = 0x08, VIX_REQUESTMSG_INCLUDES_AUTH_DATA_V1 = 0x10, VIX_REQUESTMSG_REQUIRES_VMDB_NOTIFICATION = 0x20, + VIX_REQUESTMSG_ESCAPE_XML_DATA = 0x40, }; @@ -2133,8 +2134,8 @@ enum { /* DEPRECATED VIX_COMMAND_CREATE_FLOPPY = 30, */ VIX_COMMAND_RELOAD_VM = 31, VIX_COMMAND_DELETE_VM = 32, - VIX_COMMAND_SYNCDRIVER_FREEZE = 33, - VIX_COMMAND_SYNCDRIVER_THAW = 34, + /* DEPRECATED VIX_COMMAND_SYNCDRIVER_FREEZE = 33, */ + /* DEPRECATED VIX_COMMAND_SYNCDRIVER_THAW = 34, */ /* DEPRECATED VIX_COMMAND_HOT_ADD_DISK = 35, */ /* DEPRECATED VIX_COMMAND_HOT_REMOVE_DISK = 36, */ VIX_COMMAND_SET_GUEST_PRINTER = 37, @@ -2423,6 +2424,35 @@ enum VixRunProgramResultValues { #endif +/* + * This is used to denote that the contents of a VIX XML-like response + * string has been escaped. Old Tools did not escape the contents. + * This tag is only used for existing commands that did not originally perform + * escaping. Any new command must always escape any strings passed in XML. + * See ListProcessesInGuest as an example. + * The protocol works as follows: + * 1) A client library that internally knows how to handle escaped XML opts in + * by including the VIX_REQUESTMSG_ESCAPE_XML_DATA in relevent requests. + * 2) Tools that understands the VIX_REQUESTMSG_ESCAPE_XML_DATA flag sees that + * it is set in the request, and then escapes all string data within the + * XML response. To indicate to the client that it has understood the + * request, it include the VIX_XML_ESCAPED_TAG in the response (at the + * begining of the response). + * 3) When the client library receives the response, it searches for the + * VIX_XML_ESCAPED_TAG. If it is present, it then unescapes all string + * data in the response. If the tag is not present, the client library + * assumes that the Tools did not understand VIX_REQUESTMSG_ESCAPE_XML_DATA + * and that the string data is not escaped. + * The following characters are escaped: '<', '>', and '%'. + * For new commands (starting with those released in M/N for the vSphere + * guest ops project), the escaping is exactly the same, but the + * VIX_REQUESTMSG_ESCAPE_XML_DATA flag and the VIX_XML_ESCAPED_TAG are not + * used, since both ends expect escaping. + */ +#define VIX_XML_ESCAPED_TAG "" + +#define VIX_XML_ESCAPE_CHARACTER '%' + /* *----------------------------------------------------------------------------- diff --git a/open-vm-tools/lib/include/vm_version.h b/open-vm-tools/lib/include/vm_version.h index fdc35d340..59af0ecd1 100644 --- a/open-vm-tools/lib/include/vm_version.h +++ b/open-vm-tools/lib/include/vm_version.h @@ -276,7 +276,7 @@ #define USB_ARBITRATOR_VERSION_MAJOR 8 #define USB_ARBITRATOR_VERSION_MINOR 2 -#define USB_ARBITRATOR_VERSION_Z 0 +#define USB_ARBITRATOR_VERSION_Z 2 #define USB_ARBITRATOR_VERSION_BASE USB_ARBITRATOR_VERSION_MAJOR.\ USB_ARBITRATOR_VERSION_MINOR @@ -291,7 +291,7 @@ * USB Arbitrator Component version. This version is used by the linux * installer. See USB_ARBITRATOR_COMPONENT_VERSION_NUMBER in mk/defs-onetime.mk */ -#define USB_ARBITRATOR_COMPONENT_VERSION_NUMBER "8.2.0" +#define USB_ARBITRATOR_COMPONENT_VERSION_NUMBER "8.2.2" #ifdef VMX86_VPX #define VIM_API_TYPE "VirtualCenter" @@ -519,22 +519,4 @@ typedef enum { VMX_PLATFORM_MACOS, } VMX_Platform; - -/* - * UI versions - * - * Note that these only make sense in the context of the server type - */ - -#define UI_VERSION_OLD 1 // pre-versioned UIs -#define UI_VERSION_ESX15 2 -#define UI_VERSION_GSX20 2 -#define UI_VERSION_ESX20 3 -#define UI_VERSION_GSX25 3 -// Skip one just in case we want to insert ESX21 in between here for neatness -#define UI_VERSION_GSX30 5 -#define UI_VERSION_VMSERVER10 6 - -#define UI_VERSION 6 // Current UI version - #endif /* VM_VERSION_H */ diff --git a/open-vm-tools/lib/procMgr/procMgrPosix.c b/open-vm-tools/lib/procMgr/procMgrPosix.c index cfac558b7..45f905c34 100644 --- a/open-vm-tools/lib/procMgr/procMgrPosix.c +++ b/open-vm-tools/lib/procMgr/procMgrPosix.c @@ -110,6 +110,10 @@ static Bool ProcMgrKill(pid_t pid, int sig, int timeout); +#ifdef sun +#define SOLARIS_BASH_PATH "/usr/bin/bash" +#endif + #if defined(linux) && !defined(GLIBC_VERSION_23) /* * Implements the system calls (they are not wrapped by glibc til 2.3.2). @@ -652,8 +656,40 @@ ProcMgrStartProcess(char const *cmd, // IN: UTF-8 encoded cmd if (pid == -1) { Warning("Unable to fork: %s.\n\n", strerror(errno)); } else if (pid == 0) { +#ifdef sun + /* + * On Solaris, /bin/sh is the Bourne shell, and it + * doesn't appear to have the optimization that bash does -- when + * called with -c, bash appears to just use exec() to replace itself. + * Bourne shell does a fork & exec, so 2 processes are started. + * This is bad for us because we then see the PID of the shell, not the + * app that it starts. When this PID is returned to a user to + * watch, they'll watch the wrong process. + * + * So for Solaris, use bash instead if possible. We support + * Solaris 10 and better; it contains bash, but not in its + * minimal 'core' package, so it may not exist. + */ + static const char bashShellPath[] = SOLARIS_BASH_PATH; + char *bashArgs[] = { "bash", "-c", cmdCurrent, NULL }; + static const char bourneShellPath[] = "/bin/sh"; + char *bourneArgs[] = { "sh", "-c", cmdCurrent, NULL }; + const char *shellPath; + char **args; +#else static const char shellPath[] = "/bin/sh"; char *args[] = { "sh", "-c", cmdCurrent, NULL }; +#endif + +#ifdef sun + if (File_Exists(SOLARIS_BASH_PATH)) { + shellPath = bashShellPath; + args = bashArgs; + } else { + shellPath = bourneShellPath; + args = bourneArgs; + } +#endif /* * Child diff --git a/open-vm-tools/modules/freebsd/vmxnet/if_vxn.c b/open-vm-tools/modules/freebsd/vmxnet/if_vxn.c index cd1f78f16..fe1f087aa 100644 --- a/open-vm-tools/modules/freebsd/vmxnet/if_vxn.c +++ b/open-vm-tools/modules/freebsd/vmxnet/if_vxn.c @@ -104,6 +104,7 @@ typedef struct vxn_softc { struct arpcom arpcom; #else struct ifnet *vxn_ifp; + struct ifmedia media; #endif #ifdef VXN_MPSAFE struct mtx vxn_mtx; @@ -217,6 +218,93 @@ vxn_execute_4(const vxn_softc_t *sc, /* IN: adapter */ VMXNET_COMMAND_ADDR); } +static int +vxn_check_link(vxn_softc_t *sc) +{ + uint32 status; + int ok; + + status = bus_space_read_4(sc->vxn_iobtag, sc->vxn_iobhandle, VMXNET_STATUS_ADDR); + ok = (status & VMXNET_STATUS_CONNECTED) != 0; + return ok; +} + +/* + *----------------------------------------------------------------------------- + * + * vxn_media_status -- + * + * This routine is called when the user quries the status of interface + * using ifconfig. Checks link state and updates media state accorgingly. + * + * Results: + * None. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +static void +vxn_media_status(struct ifnet * ifp, struct ifmediareq * ifmr) +{ + vxn_softc_t *sc = ifp->if_softc; + int connected = 0; + + VXN_LOCK((vxn_softc_t *)ifp->if_softc); + connected = vxn_check_link(sc); + + ifmr->ifm_status = IFM_AVALID; + ifmr->ifm_active = IFM_ETHER; + + if (!connected) { + ifmr->ifm_status &= ~IFM_ACTIVE; + VXN_UNLOCK((vxn_softc_t *)ifp->if_softc); + return; + } + + ifmr->ifm_status |= IFM_ACTIVE; + + VXN_UNLOCK((vxn_softc_t *)ifp->if_softc); + return; +} + + +/* + *----------------------------------------------------------------------------- + * + * vxn_media_change -- + * + * This routine is called when the user changes speed/duplex using + * media/mediopt option with ifconfig. + * + * Results: + * Returns 0 for success, error code otherwise. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------------- + */ + +static int +vxn_media_change(struct ifnet * ifp) +{ + vxn_softc_t *sc = ifp->if_softc; + struct ifmedia *ifm = &sc->media; + + if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) + return (EINVAL); + + if (IFM_SUBTYPE(ifm->ifm_media) != IFM_AUTO) + printf("Media subtype is not AUTO, it is : %d.\n", + IFM_SUBTYPE(ifm->ifm_media)); + + return (0); +} + + /* *----------------------------------------------------------------------------- * vxn_attach -- @@ -393,7 +481,8 @@ vxn_attach(device_t dev) * read the MAC address from the device */ for (i = 0; i < 6; i++) { - mac[i] = bus_space_read_1(sc->vxn_iobtag, sc->vxn_iobhandle, VMXNET_MAC_ADDR + i); + mac[i] = bus_space_read_1(sc->vxn_iobtag, sc->vxn_iobhandle, VMXNET_MAC_ADDR + + i); } #ifdef VXN_NEEDARPCOM @@ -414,9 +503,22 @@ vxn_attach(device_t dev) sc->vxn_num_tx_bufs, (int)sizeof(Vmxnet2_TxRingEntry), driverDataSize); + /* + * Specify the media types supported by this adapter and register + * callbacks to update media and link information + */ + ifmedia_init(&sc->media, IFM_IMASK, vxn_media_change, + vxn_media_status); + ifmedia_add(&sc->media, IFM_ETHER | IFM_FDX, 0, NULL); + ifmedia_add(&sc->media, IFM_ETHER | IFM_1000_T | IFM_FDX, 0, NULL); + ifmedia_add(&sc->media, IFM_ETHER | IFM_1000_T, 0, NULL); + ifmedia_add(&sc->media, IFM_ETHER | IFM_AUTO, 0, NULL); + ifmedia_set(&sc->media, IFM_ETHER | IFM_AUTO); + + goto done; - fail: +fail: if (sc->vxn_intrhand != NULL) { bus_teardown_intr(dev, sc->vxn_irq, sc->vxn_intrhand); @@ -468,8 +570,7 @@ vxn_detach(device_t dev) sc = device_get_softc(dev); ifp = VXN_SC2IFP(sc); - - if (device_get_state(dev) >= DS_ATTACHED) { + if (device_is_attached(dev)) { vxn_stop(sc); /* * detach from stack @@ -689,7 +790,8 @@ vxn_initl(vxn_softc_t *sc) { Vmxnet2_DriverData *dd = sc->vxn_dd; struct ifnet *ifp = VXN_SC2IFP(sc); - uint32 r; + uint32 r, i; + u_char mac_addr[6]; VXN_LOCK_ASSERT(sc); @@ -702,6 +804,28 @@ vxn_initl(vxn_softc_t *sc) return; } + /* Get MAC address from interface and set it in hardware */ +#if __FreeBSD_version >= 700000 + printf("addrlen : %d. \n", ifp->if_addrlen); + bcopy(LLADDR((struct sockaddr_dl *)ifp->if_addr->ifa_addr), mac_addr, + ifp->if_addrlen > 6 ? 6 : ifp->if_addrlen); +#else + if (!ifaddr_byindex(ifp->if_index)) { + printf("vxn:%d Invalid link address, interface index :%d.\n", + VXN_IF_UNIT(ifp), ifp->if_index); + } else { + bcopy(LLADDR((struct sockaddr_dl *)ifaddr_byindex(ifp->if_index)->ifa_addr), + mac_addr, ifp->if_addrlen); + } +#endif + printf("vxn%d: MAC Address : %02x:%02x:%02x:%02x:%02x:%02x \n", + VXN_IF_UNIT(ifp), mac_addr[0], mac_addr[1], mac_addr[2], + mac_addr[3], mac_addr[4], mac_addr[5]); + for (i = 0; i < 6; i++) { + bus_space_write_1(sc->vxn_iobtag, sc->vxn_iobhandle, VMXNET_MAC_ADDR + + i, mac_addr[i]); + } + /* * Start hardware */ @@ -1008,6 +1132,10 @@ vxn_ioctl(struct ifnet *ifp, u_long command, caddr_t data) error = 0; break; + case SIOCSIFMEDIA: + case SIOCGIFMEDIA: + ifmedia_ioctl(ifp, (struct ifreq *)data, &sc->media, command); + default: error = EINVAL; break; diff --git a/open-vm-tools/services/plugins/vix/vixTools.c b/open-vm-tools/services/plugins/vix/vixTools.c index bcbadd946..37c9be145 100644 --- a/open-vm-tools/services/plugins/vix/vixTools.c +++ b/open-vm-tools/services/plugins/vix/vixTools.c @@ -92,6 +92,7 @@ #include "unicode.h" #include "hashTable.h" #include "su.h" +#include "escape.h" #if defined(linux) || defined(_WIN32) #include "netutil.h" @@ -292,6 +293,7 @@ static gboolean VixToolsMonitorStartProgram(void *clientData); static void VixToolsPrintFileInfo(const char *filePathName, char *fileName, + Bool escapeStrs, char **destPtr, char *endDestPtr); @@ -395,6 +397,14 @@ static VixError VixToolsListProcesses(VixCommandRequestHeader *requestMsg, size_t maxBufferSize, char **result); +static VixError VixToolsPrintProcInfoEx(DynBuf *dstBuffer, + const char *name, + uint64 pid, + const char *user, + int start, + int exitCode, + int exitTime); + static VixError VixToolsListDirectory(VixCommandRequestHeader *requestMsg, size_t maxBufferSize, char **result); @@ -428,6 +438,17 @@ static VixError VixToolsProcessHgfsPacket(VixCommandHgfsSendPacket *requestMsg, static VixError VixToolsListFileSystems(VixCommandRequestHeader *requestMsg, char **result); +#if defined(_WIN32) || defined(linux) +static VixError VixToolsPrintFileSystemInfo(char **destPtr, + const char *endDestPtr, + const char *name, + uint64 size, + uint64 freeSpace, + const char *type, + Bool escapeStrs, + Bool *truncated); +#endif + static VixError VixToolsValidateCredentials(VixCommandRequestHeader *requestMsg); static VixError VixToolsAcquireCredentials(VixCommandRequestHeader *requestMsg, @@ -486,6 +507,8 @@ static void VixToolsFreeEnvp(char **envp); static VixError VixToolsRewriteError(uint32 opCode, VixError origError); +static size_t VixToolsXMLStringEscapedLen(const char *str, Bool escapeStr); + /* *----------------------------------------------------------------------------- @@ -3447,12 +3470,34 @@ VixToolsGetMultipleEnvVarsForUser(void *userToken, // IN value = VixToolsGetEnvFromUserEnvironment(env, names); if (NULL != value) { char *tmp = resultLocal; + char *tmpVal; + char *escapedName; + + escapedName = VixToolsEscapeXMLString(names); + if (NULL == escapedName) { + err = VIX_E_OUT_OF_MEMORY; + goto loopCleanup; + } + + tmpVal = VixToolsEscapeXMLString(value); + if (NULL == tmpVal) { + err = VIX_E_OUT_OF_MEMORY; + goto loopCleanup; + } + free(value); + value = tmpVal; + resultLocal = Str_Asprintf(NULL, "%s%s=%s", - tmp, names, value); + tmp, escapedName, value); free(tmp); - free(value); if (NULL == resultLocal) { err = VIX_E_OUT_OF_MEMORY; + } + + loopCleanup: + free(value); + free(escapedName); + if (VIX_OK != err) { goto abort; } } @@ -3461,9 +3506,11 @@ VixToolsGetMultipleEnvVarsForUser(void *userToken, // IN } *result = resultLocal; + resultLocal = NULL; err = VIX_OK; abort: + free(resultLocal); VixToolsDestroyUserEnvironment(env); return err; @@ -3512,6 +3559,16 @@ VixToolsGetAllEnvVarsForUser(void *userToken, // IN while ((envVar = VixToolsGetNextEnvVar(itr)) != NULL) { char *tmp = resultLocal; + char *tmpVal; + + tmpVal = VixToolsEscapeXMLString(envVar); + free(envVar); + if (NULL == tmpVal) { + err = VIX_E_OUT_OF_MEMORY; + goto abort; + } + envVar = tmpVal; + resultLocal = Str_Asprintf(NULL, "%s%s", tmp, envVar); free(tmp); free(envVar); @@ -4153,7 +4210,7 @@ VixToolsListProcesses(VixCommandRequestHeader *requestMsg, // IN char **result) // OUT { VixError err = VIX_OK; - int index; + int i; static char resultBuffer[GUESTMSG_MAX_IN_SIZE]; ProcMgr_ProcList *procList = NULL; char *destPtr; @@ -4162,6 +4219,9 @@ VixToolsListProcesses(VixCommandRequestHeader *requestMsg, // IN size_t procBufSize; Bool impersonatingVMWareUser = FALSE; void *userToken = NULL; + Bool escapeStrs; + char *escapedName = NULL; + char *escapedUser = NULL; ASSERT(maxBufferSize <= GUESTMSG_MAX_IN_SIZE); @@ -4174,6 +4234,9 @@ VixToolsListProcesses(VixCommandRequestHeader *requestMsg, // IN } impersonatingVMWareUser = TRUE; + escapeStrs = (requestMsg->requestFlags & + VIX_REQUESTMSG_ESCAPE_XML_DATA) != 0; + procList = ProcMgr_ListProcesses(); if (NULL == procList) { err = FoundryToolsDaemon_TranslateSystemErr(); @@ -4181,26 +4244,62 @@ VixToolsListProcesses(VixCommandRequestHeader *requestMsg, // IN } endDestPtr = resultBuffer + maxBufferSize; - for (index = 0; index < procList->procCount; index++) { + + if (escapeStrs) { + destPtr += Str_Sprintf(destPtr, endDestPtr - destPtr, "%s", + VIX_XML_ESCAPED_TAG); + } + + for (i = 0; i < procList->procCount; i++) { + const char *name; + const char *user; + + if (escapeStrs) { + name = escapedName = + VixToolsEscapeXMLString(procList->procCmdList[i]); + if (NULL == escapedName) { + err = VIX_E_OUT_OF_MEMORY; + goto abort; + } + } else { + name = procList->procCmdList[i]; + } + + if ((NULL != procList->procOwnerList) && + (NULL != procList->procOwnerList[i])) { + if (escapeStrs) { + user = escapedUser = + VixToolsEscapeXMLString(procList->procOwnerList[i]); + if (NULL == escapedUser) { + err = VIX_E_OUT_OF_MEMORY; + goto abort; + } + } else { + user = procList->procOwnerList[i]; + } + } else { + user = ""; + } + procBufPtr = Str_Asprintf(&procBufSize, "%s%d" #if defined(_WIN32) "%d" #endif "%s%d", - procList->procCmdList[index], - (int) procList->procIdList[index], + name, + (int) procList->procIdList[i], #if defined(_WIN32) - (int) procList->procDebugged[index], + (int) procList->procDebugged[i], #endif - (NULL == procList->procOwnerList - || NULL == procList->procOwnerList[index]) - ? "" - : procList->procOwnerList[index], + user, (NULL == procList->startTime) ? 0 - : (int) procList->startTime[index]); - + : (int) procList->startTime[i]); + if (NULL == procBufPtr) { + err = VIX_E_OUT_OF_MEMORY; + goto abort; + } if ((destPtr + procBufSize) < endDestPtr) { destPtr += Str_Sprintf(destPtr, endDestPtr - destPtr, "%s", procBufPtr); @@ -4210,6 +4309,10 @@ VixToolsListProcesses(VixCommandRequestHeader *requestMsg, // IN goto abort; } free(procBufPtr); + free(escapedName); + escapedName = NULL; + free(escapedUser); + escapedUser = NULL; } abort: @@ -4218,6 +4321,8 @@ abort: } VixToolsLogoutUser(userToken); ProcMgr_FreeProcList(procList); + free(escapedName); + free(escapedUser); *result = resultBuffer; @@ -4308,20 +4413,13 @@ VixToolsListProcessesExGenerateData(uint32 numPids, // IN size_t *resultSize, // OUT char **resultBuffer) // OUT { - int i; - int j; VixError err = VIX_OK; - char *procBufPtr = NULL; - size_t procBufSize; ProcMgr_ProcList *procList = NULL; DynBuf dynBuffer; VixToolsExitedProgramState *epList; + int i; + int j; Bool bRet; - static const char *procInfoFormatString = - "%s%"FMT64"d" - "%s%d" - "%d%d" - ""; DynBuf_Init(&dynBuffer); @@ -4342,18 +4440,14 @@ VixToolsListProcessesExGenerateData(uint32 numPids, // IN epList = exitedProcessList; while (epList) { if (pids[i] == epList->pid) { - procBufPtr = Str_Asprintf(&procBufSize, - procInfoFormatString, - epList->fullCommandLine, - epList->pid, - epList->user, - (int) epList->startTime, - epList->exitCode, - (int) epList->endTime); - bRet = DynBuf_Append(&dynBuffer, procBufPtr, procBufSize); - free(procBufPtr); - if (!bRet) { - err = VIX_E_OUT_OF_MEMORY; + err = VixToolsPrintProcInfoEx(&dynBuffer, + epList->fullCommandLine, + epList->pid, + epList->user, + (int) epList->startTime, + epList->exitCode, + (int) epList->endTime); + if (VIX_OK != err) { goto abort; } } @@ -4363,18 +4457,14 @@ VixToolsListProcessesExGenerateData(uint32 numPids, // IN } else { epList = exitedProcessList; while (epList) { - procBufPtr = Str_Asprintf(&procBufSize, - procInfoFormatString, - epList->fullCommandLine, - epList->pid, - epList->user, - (int) epList->startTime, - epList->exitCode, - (int) epList->endTime); - bRet = DynBuf_Append(&dynBuffer, procBufPtr, procBufSize); - free(procBufPtr); - if (!bRet) { - err = VIX_E_OUT_OF_MEMORY; + err = VixToolsPrintProcInfoEx(&dynBuffer, + epList->fullCommandLine, + epList->pid, + epList->user, + (int) epList->startTime, + epList->exitCode, + (int) epList->endTime); + if (VIX_OK != err) { goto abort; } epList = epList->next; @@ -4396,22 +4486,16 @@ VixToolsListProcessesExGenerateData(uint32 numPids, // IN continue; } if (pids[i] == procList->procIdList[j]) { - procBufPtr = Str_Asprintf(&procBufSize, - procInfoFormatString, - procList->procCmdList[j], - (uint64) procList->procIdList[j], - (NULL == procList->procOwnerList - || NULL == procList->procOwnerList[j]) - ? "" - : procList->procOwnerList[j], - (NULL == procList->startTime) - ? 0 - : (int) procList->startTime[j], - 0, 0); // eCode, eTime - bRet = DynBuf_Append(&dynBuffer, procBufPtr, procBufSize); - free(procBufPtr); - if (!bRet) { - err = VIX_E_OUT_OF_MEMORY; + err = VixToolsPrintProcInfoEx(&dynBuffer, + procList->procCmdList[i], + procList->procIdList[i], + (NULL == procList->procOwnerList + || NULL == procList->procOwnerList[i]) + ? "" : procList->procOwnerList[i], + (NULL == procList->startTime) + ? 0 : (int) procList->startTime[i], + 0, 0); + if (VIX_OK != err) { goto abort; } } @@ -4423,22 +4507,16 @@ VixToolsListProcessesExGenerateData(uint32 numPids, // IN if (VixToolsFindExitedProgramState(procList->procIdList[i])) { continue; } - procBufPtr = Str_Asprintf(&procBufSize, - procInfoFormatString, - procList->procCmdList[i], - (uint64) procList->procIdList[i], - (NULL == procList->procOwnerList - || NULL == procList->procOwnerList[i]) - ? "" - : procList->procOwnerList[i], - (NULL == procList->startTime) - ? 0 - : (int) procList->startTime[i], - 0, 0); // eCode, eTime - bRet = DynBuf_Append(&dynBuffer, procBufPtr, procBufSize); - free(procBufPtr); - if (!bRet) { - err = VIX_E_OUT_OF_MEMORY; + err = VixToolsPrintProcInfoEx(&dynBuffer, + procList->procCmdList[i], + procList->procIdList[i], + (NULL == procList->procOwnerList + || NULL == procList->procOwnerList[i]) + ? "" : procList->procOwnerList[i], + (NULL == procList->startTime) + ? 0 : (int) procList->startTime[i], + 0, 0); + if (VIX_OK != err) { goto abort; } } @@ -4481,6 +4559,7 @@ abort: * *----------------------------------------------------------------------------- */ + static Bool VixToolsGetUserName(wchar_t **userName) // OUT { @@ -4755,6 +4834,80 @@ abort: } // VixToolsListProcessesEx +/* + *----------------------------------------------------------------------------- + * + * VixToolsPrintProcInfoEx -- + * + * Appends a single process entry to the XML-like string starting at + * *destPtr. + * + * Results: + * VixError + * + * Side effects: + * None + * + *----------------------------------------------------------------------------- + */ + +static VixError +VixToolsPrintProcInfoEx(DynBuf *dstBuffer, // IN/OUT + const char *name, // IN + uint64 pid, // IN + const char *user, // IN + int start, // IN + int exitCode, // IN + int exitTime) // IN +{ + VixError err; + char *escapedName; + char *escapedUser = NULL; + size_t bytesPrinted; + char *procInfoEntry; + Bool success; + + escapedName = VixToolsEscapeXMLString(name); + if (NULL == escapedName) { + err = VIX_E_OUT_OF_MEMORY; + goto abort; + } + + escapedUser = VixToolsEscapeXMLString(user); + if (NULL == escapedUser) { + err = VIX_E_OUT_OF_MEMORY; + goto abort; + } + + procInfoEntry = Str_Asprintf(&bytesPrinted, + "%s%"FMT64"d" + "%s%d" + "%d%d" + "", + escapedName, pid, escapedUser, start, exitCode, + exitTime); + if (NULL == procInfoEntry) { + err = VIX_E_OUT_OF_MEMORY; + goto abort; + } + + success = DynBuf_Append(dstBuffer, procInfoEntry, bytesPrinted); + free(procInfoEntry); + if (!success) { + err = VIX_E_OUT_OF_MEMORY; + goto abort; + } + + err = VIX_OK; + +abort: + free(escapedName); + free(escapedUser); + + return err; +} + + /* *----------------------------------------------------------------------------- * @@ -4991,6 +5144,7 @@ VixToolsListDirectory(VixCommandRequestHeader *requestMsg, // IN Bool isLegacyFormat; VMAutomationRequestParser parser; int dirPathLen; + Bool escapeStrs; legacyListRequest = (VixMsgSimpleFileRequest *) requestMsg; if (legacyListRequest->fileOptions & VIX_LIST_DIRECTORY_USE_OFFSET) { @@ -5039,6 +5193,9 @@ VixToolsListDirectory(VixCommandRequestHeader *requestMsg, // IN } impersonatingVMWareUser = TRUE; + escapeStrs = (requestMsg->requestFlags & + VIX_REQUESTMSG_ESCAPE_XML_DATA) != 0; + if (!(File_IsDirectory(dirPathName))) { err = VIX_E_NOT_A_DIRECTORY; goto abort; @@ -5055,6 +5212,9 @@ VixToolsListDirectory(VixCommandRequestHeader *requestMsg, // IN * max number of entries we can store. */ resultBufferSize = 3; // truncation bool + space + '\0' + if (escapeStrs) { + resultBufferSize += strlen(VIX_XML_ESCAPED_TAG); + } lastGoodResultBufferSize = resultBufferSize; ASSERT_NOT_IMPLEMENTED(lastGoodResultBufferSize < maxBufferSize); formatStringLength = strlen(fileInfoFormatString); @@ -5063,7 +5223,8 @@ VixToolsListDirectory(VixCommandRequestHeader *requestMsg, // IN currentFileName = fileNameList[fileNum]; resultBufferSize += formatStringLength; - resultBufferSize += strlen(currentFileName); + resultBufferSize += VixToolsXMLStringEscapedLen(currentFileName, + escapeStrs); resultBufferSize += 2; // DIRSEPC chars resultBufferSize += 10 + 20 + 20; // properties + size + modTime @@ -5104,6 +5265,11 @@ VixToolsListDirectory(VixCommandRequestHeader *requestMsg, // IN } } + if (escapeStrs) { + destPtr += Str_Sprintf(destPtr, endDestPtr - destPtr, "%s", + VIX_XML_ESCAPED_TAG); + } + for (fileNum = offset; fileNum < lastGoodNumFiles; fileNum++) { /* File_ListDirectory never returns "." or ".." */ char *pathName; @@ -5113,7 +5279,8 @@ VixToolsListDirectory(VixCommandRequestHeader *requestMsg, // IN pathName = Str_SafeAsprintf(NULL, "%s%s%s", dirPathName, DIRSEPS, currentFileName); - VixToolsPrintFileInfo(pathName, currentFileName, &destPtr, endDestPtr); + VixToolsPrintFileInfo(pathName, currentFileName, escapeStrs, &destPtr, + endDestPtr); free(pathName); } // for (fileNum = 0; fileNum < lastGoodNumFiles; fileNum++) @@ -5465,13 +5632,14 @@ VixToolsGetFileExtendedInfoLength(const char *filePathName, // IN char *symlinkTarget; symlinkTarget = Posix_ReadLink(filePathName); if (NULL != symlinkTarget) { - fileExtendedInfoBufferSize += strlen(symlinkTarget); + fileExtendedInfoBufferSize += + VixToolsXMLStringEscapedLen(symlinkTarget, TRUE); } free(symlinkTarget); } #endif - fileExtendedInfoBufferSize += strlen(fileName); + fileExtendedInfoBufferSize += VixToolsXMLStringEscapedLen(fileName, TRUE); return fileExtendedInfoBufferSize; } @@ -5549,7 +5717,7 @@ VixToolsGetFileInfo(VixCommandRequestHeader *requestMsg, // IN * Print the result buffer */ destPtr = resultBuffer; - VixToolsPrintFileInfo(filePathName, "", &destPtr, resultBuffer + resultBufferSize); + VixToolsPrintFileInfo(filePathName, "", FALSE, &destPtr, resultBuffer + resultBufferSize); abort: if (impersonatingVMWareUser) { @@ -5833,12 +6001,14 @@ abort: static void VixToolsPrintFileInfo(const char *filePathName, // IN char *fileName, // IN - char **destPtr, // IN - char *endDestPtr) // OUT + Bool escapeStrs, // IN + char **destPtr, // IN/OUT + char *endDestPtr) // IN { int64 fileSize = 0; int64 modTime; int32 fileProperties = 0; + char *escapedFileName = NULL; modTime = File_GetModTime(filePathName); if (File_IsDirectory(filePathName)) { @@ -5852,6 +6022,11 @@ VixToolsPrintFileInfo(const char *filePathName, // IN } } + if (escapeStrs) { + fileName = escapedFileName = VixToolsEscapeXMLString(fileName); + ASSERT_MEM_ALLOC(NULL != escapedFileName); + } + *destPtr += Str_Sprintf(*destPtr, endDestPtr - *destPtr, fileInfoFormatString, @@ -5859,6 +6034,7 @@ VixToolsPrintFileInfo(const char *filePathName, // IN fileProperties, fileSize, modTime); + free(escapedFileName); } // VixToolsPrintFileInfo @@ -5879,8 +6055,8 @@ VixToolsPrintFileInfo(const char *filePathName, // IN static void VixToolsPrintFileExtendedInfo(const char *filePathName, // IN const char *fileName, // IN - char **destPtr, // IN - char *endDestPtr) // OUT + char **destPtr, // IN/OUT + char *endDestPtr) // IN { #if defined(_WIN32) || defined(linux) int64 fileSize = 0; @@ -5897,8 +6073,10 @@ VixToolsPrintFileExtendedInfo(const char *filePathName, // IN int ownerId = 0; int groupId = 0; char *symlinkTarget = NULL; + char *tmp; #endif struct stat statbuf; + char *escapedFileName = NULL; /* * First check for symlink -- File_IsDirectory() will lie @@ -5927,6 +6105,11 @@ VixToolsPrintFileExtendedInfo(const char *filePathName, // IN if (NULL == symlinkTarget) { symlinkTarget = Util_SafeStrdup(""); } + + tmp = VixToolsEscapeXMLString(symlinkTarget); + ASSERT_MEM_ALLOC(NULL != tmp); + free(symlinkTarget); + symlinkTarget = tmp; #endif #ifdef _WIN32 @@ -5961,11 +6144,14 @@ VixToolsPrintFileExtendedInfo(const char *filePathName, // IN __FUNCTION__, filePathName, errno); } + escapedFileName = VixToolsEscapeXMLString(fileName); + ASSERT_MEM_ALLOC(NULL != escapedFileName); + #ifdef _WIN32 *destPtr += Str_Sprintf(*destPtr, endDestPtr - *destPtr, fileExtendedInfoWindowsFormatString, - fileName, + escapedFileName, fileProperties, fileSize, modTime, @@ -5977,7 +6163,7 @@ VixToolsPrintFileExtendedInfo(const char *filePathName, // IN *destPtr += Str_Sprintf(*destPtr, endDestPtr - *destPtr, fileExtendedInfoLinuxFormatString, - fileName, + escapedFileName, fileProperties, fileSize, modTime, @@ -5988,6 +6174,7 @@ VixToolsPrintFileExtendedInfo(const char *filePathName, // IN symlinkTarget); free(symlinkTarget); #endif + free(escapedFileName); #endif // defined(_WIN32) || defined(linux) } // VixToolsPrintFileExtendedInfo @@ -6026,8 +6213,8 @@ VixToolsPrintFileExtendedInfoEx(const char *filePathName, // IN destPtr = resultBuffer; endDestPtr = resultBuffer + resultBufferSize; - VixToolsPrintFileExtendedInfo(filePathName, filePathName, - &destPtr, endDestPtr); + VixToolsPrintFileExtendedInfo(filePathName, filePathName, &destPtr, + endDestPtr); *destPtr = '\0'; return resultBuffer; @@ -7304,13 +7491,9 @@ VixToolsListFileSystems(VixCommandRequestHeader *requestMsg, // IN void *userToken = NULL; char *destPtr; char *endDestPtr; + Bool escapeStrs; #if defined(_WIN32) || defined(linux) - const char *listFileSystemsFormatString = "" - "%s" - "%"FMT64"u" - "%"FMT64"u" - "%s" - ""; + Bool truncated; #endif #if defined(_WIN32) Unicode *driveList = NULL; @@ -7339,6 +7522,9 @@ VixToolsListFileSystems(VixCommandRequestHeader *requestMsg, // IN } impersonatingVMWareUser = TRUE; + escapeStrs = (requestMsg->requestFlags & + VIX_REQUESTMSG_ESCAPE_XML_DATA) != 0; + #if defined(_WIN32) numDrives = Win32U_GetLogicalDriveStrings(&driveList); if (-1 == numDrives) { @@ -7348,6 +7534,11 @@ VixToolsListFileSystems(VixCommandRequestHeader *requestMsg, // IN goto abort; } + if (escapeStrs) { + destPtr += Str_Sprintf(destPtr, endDestPtr - destPtr, "%s", + VIX_XML_ESCAPED_TAG); + } + for (i = 0; i < numDrives; i++) { if (!Win32U_GetDiskFreeSpaceEx(driveList[i], (PULARGE_INTEGER) &freeBytesToUser, @@ -7371,14 +7562,14 @@ VixToolsListFileSystems(VixCommandRequestHeader *requestMsg, // IN NULL, NULL, &fileSystemType); - - destPtr += Str_Sprintf(destPtr, endDestPtr - destPtr, - listFileSystemsFormatString, - driveList[i], - totalBytesToUser, - freeBytesToUser, - fileSystemType); - + err = VixToolsPrintFileSystemInfo(&destPtr, endDestPtr, + driveList[i], totalBytesToUser, + freeBytesToUser, + fileSystemType ? fileSystemType : "", + escapeStrs, &truncated); + if ((VIX_OK != err) || truncated) { + goto abort; + } Unicode_Free(fileSystemType); } @@ -7404,13 +7595,13 @@ VixToolsListFileSystems(VixCommandRequestHeader *requestMsg, // IN } size = (uint64) statfsbuf.f_blocks * (uint64) statfsbuf.f_bsize; freeSpace = (uint64) statfsbuf.f_bfree * (uint64) statfsbuf.f_bsize; - destPtr += Str_Sprintf(destPtr, endDestPtr - destPtr, - listFileSystemsFormatString, - MNTINFO_NAME(mnt), - size, - freeSpace, - MNTINFO_FSTYPE(mnt)); - + err = VixToolsPrintFileSystemInfo(&destPtr, endDestPtr, + MNTINFO_NAME(mnt), size, freeSpace, + MNTINFO_FSTYPE(mnt), escapeStrs, + &truncated); + if ((VIX_OK != err) || truncated) { + goto abort; + } } CLOSE_MNTFILE(fp); #else @@ -7438,6 +7629,88 @@ abort: return(err); } // VixToolsListFileSystems + +#if defined(_WIN32) || defined(linux) +/* + *----------------------------------------------------------------------------- + * + * VixToolsPrintFileSystemInfo -- + * + * Appends a single file system entry to the XML-like string starting at + * *destPtr. + * + * Results: + * VixError + * + * Side effects: + * None + * + *----------------------------------------------------------------------------- + */ + +static VixError +VixToolsPrintFileSystemInfo(char **destPtr, // IN/OUT + const char *endDestPtr, // IN + const char *name, // IN + uint64 size, // IN + uint64 freeSpace, // IN + const char *type, // IN + Bool escapeStrs, // IN + Bool *truncated) // OUT +{ + VixError err; + char *escapedName = NULL; + char *escapedType = NULL; + int bytesPrinted; + + ASSERT(endDestPtr > *destPtr); + + *truncated = FALSE; + + if (escapeStrs) { + name = escapedName = VixToolsEscapeXMLString(name); + if (NULL == escapedName) { + err = VIX_E_OUT_OF_MEMORY; + goto abort; + } + + type = escapedType = VixToolsEscapeXMLString(type); + if (NULL == escapedType) { + err = VIX_E_OUT_OF_MEMORY; + goto abort; + } + } + + bytesPrinted = Str_Snprintf(*destPtr, endDestPtr - *destPtr, + "" + "%s" + "%"FMT64"u" + "%"FMT64"u" + "%s" + "", + name, size, freeSpace, type); + if (bytesPrinted != -1) { + *destPtr += bytesPrinted; + } else { // out of space + **destPtr = '\0'; + Debug("%s: file system list results too large, truncating", + __FUNCTION__); + *truncated = TRUE; + err = VIX_OK; + goto abort; + } + + err = VIX_OK; + +abort: + free(escapedName); + free(escapedType); + + return err; +} +#endif // #if defined(_WIN32) || defined(linux) + + /* *----------------------------------------------------------------------------- * @@ -8480,7 +8753,7 @@ VixTools_ProcessVixCommand(VixCommandRequestHeader *requestMsg, // IN //////////////////////////////////// case VIX_COMMAND_INITIATE_FILE_TRANSFER_TO_GUEST: err = VixToolsInitiateFileTransferToGuest(requestMsg); - break; + break; //////////////////////////////////// case VIX_COMMAND_VALIDATE_CREDENTIALS: @@ -8810,3 +9083,95 @@ VixToolsEnableStaticOnPrimary(const char *ipAddr, // IN return ret; } #endif + + +/* + *----------------------------------------------------------------------------- + * + * VixToolsEscapeXMLString -- + * + * Escapes a string to be included in VMAutomation XML. + * + * Results: + * Pointer to a heap-allocated escaped string. + * + * Side effects: + * None + * + *----------------------------------------------------------------------------- + */ + +char * +VixToolsEscapeXMLString(const char *str) // IN +{ + static const int bytesToEscape[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // '%' + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, // '<' and '>' + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }; + + return Escape_Do(VIX_XML_ESCAPE_CHARACTER, bytesToEscape, str, strlen(str), + NULL); +} + + +/* + *----------------------------------------------------------------------------- + * + * VixToolsXMLStringEscapedLen -- + * + * Computes the length of the supplied string if it were escaped + * (if escapeStr is TRUE), or the length of the string as is. + * + * Results: + * The length. + * + * Side effects: + * None + * + *----------------------------------------------------------------------------- + */ + +static size_t +VixToolsXMLStringEscapedLen(const char *str, // IN + Bool escapeStr) // IN +{ + if (escapeStr) { + size_t totalLen = 0; + + while (TRUE) { + size_t nextLen = strcspn(str, "<>%"); + + totalLen += nextLen; + if ('\0' == str[nextLen]) { + break; + } + + /* + * str[nextLen] is a character that needs to be escaped. Each + * escapeStr that is escaped will take up 3 bytes (an escape + * character and two hex digits) in the escaped string. + */ + + totalLen += 3; + str += nextLen + 1; + } + + return totalLen; + } else { + return strlen(str); + } +} diff --git a/open-vm-tools/services/plugins/vix/vixToolsInt.h b/open-vm-tools/services/plugins/vix/vixToolsInt.h index 32e453fc7..12249863c 100644 --- a/open-vm-tools/services/plugins/vix/vixToolsInt.h +++ b/open-vm-tools/services/plugins/vix/vixToolsInt.h @@ -65,6 +65,8 @@ VixError VixToolsValidateEnviron(char const * const *environ); char *VixToolsGetEnvVarFromEnvBlock(const wchar_t *envBlock, const char *envVarName); +char *VixToolsEscapeXMLString(const char *str); + #ifdef _WIN32 VixError VixToolsGetEnvBlock(void *userToken, wchar_t **envBlock);