From: Oliver Kurth Date: Tue, 18 Dec 2018 22:12:19 +0000 (-0800) Subject: Updates to the DeployPkg guest customization source code. X-Git-Tag: stable-11.0.0~269 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e5f79d1591677fd83173203e552e5a495109137f;p=thirdparty%2Fopen-vm-tools.git Updates to the DeployPkg guest customization source code. --- diff --git a/open-vm-tools/libDeployPkg/linuxDeployment.c b/open-vm-tools/libDeployPkg/linuxDeployment.c index 34c8b956b..0c853cda7 100644 --- a/open-vm-tools/libDeployPkg/linuxDeployment.c +++ b/open-vm-tools/libDeployPkg/linuxDeployment.c @@ -35,16 +35,18 @@ #include #include #include +#include "str.h" #include "mspackWrapper.h" #include "deployPkgFormat.h" #include "deployPkg/linuxDeployment.h" #include "imgcust-common/process.h" -#include "imgcust-guest/guestcust-events.h" #include "linuxDeploymentUtilities.h" #include "mspackWrapper.h" #include "vmware/guestrpc/deploypkg.h" +#include "vmware/guestrpc/guestcust-events.h" #include "vmware/tools/guestrpc.h" +#include #include #include @@ -74,9 +76,9 @@ VM_EMBED_VERSION(SYSIMAGE_VERSION_EXT_STR); #define IMC_TMP_PATH_VAR "@@IMC_TMP_PATH_VAR@@" #endif -// '/tmp' below will be addressed by PR 1601405. -#ifndef TMP_DIR_PATH_PATTERN -#define TMP_DIR_PATH_PATTERN "/tmp/.vmware-imgcust-dXXXXXX" +// Use it to create random name folder for extracting the package +#ifndef IMC_DIR_PATH_PATTERN +#define IMC_DIR_PATH_PATTERN "/.vmware-imgcust-dXXXXXX" #endif #ifndef BASEFILENAME @@ -100,6 +102,9 @@ static const char BACKSLASH = '\\'; static const char* INPROGRESS = "INPROGRESS"; static const char* DONE = "Done"; static const char* ERRORED = "ERRORED"; +static const char* RUNDIR = "/run"; +static const char* VARRUNDIR = "/var/run"; +static const char* TMPDIR = "/tmp"; // Possible return codes from perl script static const int CUST_SUCCESS = 0; @@ -171,7 +176,8 @@ Panic(const char *fmtstr, ...) char *tmp = Util_SafeMalloc(MAXSTRING); va_start(args, fmtstr); - vsprintf(tmp, fmtstr, args); + Str_Vsnprintf(tmp, MAXSTRING, fmtstr, args); + va_end(args); sLog(log_error, "Panic callback invoked: %s\n", tmp); @@ -201,7 +207,8 @@ Debug(const char *fmtstr, ...) char *tmp = Util_SafeMalloc(MAXSTRING); va_start(args, fmtstr); - vsprintf(tmp, fmtstr, args); + Str_Vsnprintf(tmp, MAXSTRING, fmtstr, args); + va_end(args); sLog(log_debug, "Debug callback invoked: %s\n", tmp); @@ -245,10 +252,11 @@ SetCustomizationStatusInVmxEx(int customizationState, Bool success; if (errMsg) { - msg = malloc(strlen(CABCOMMANDLOG) + 1 + strlen(errMsg) + 1); + int msg_size = strlen(CABCOMMANDLOG) + 1 + strlen(errMsg) + 1; + msg = malloc(msg_size); strcpy (msg, CABCOMMANDLOG); - strcat (msg, "@"); - strcat (msg, errMsg); + Str_Strcat(msg, "@", msg_size); + Str_Strcat(msg, errMsg, msg_size); } else { msg = malloc(strlen(CABCOMMANDLOG) + 1); strcpy (msg, CABCOMMANDLOG); @@ -375,7 +383,8 @@ SetDeployError(const char* format, ...) if (tmp) { va_start(args, format); - vsprintf(tmp, format, args); + Str_Vsnprintf(tmp, MAXSTRING, format, args); + va_end(args); } if (gDeployError) { @@ -618,7 +627,8 @@ GetPackageInfo(const char* packageName, static DeployPkgStatus Touch(const char* state) { - char* fileName = malloc(strlen(BASEFILENAME) + 1 + strlen(state) + 1); + int fileNameSize = strlen(BASEFILENAME) + 1 + strlen(state) + 1; + char* fileName = malloc(fileNameSize); int fd; sLog(log_info, "ENTER STATE %s \n", state); @@ -628,8 +638,8 @@ Touch(const char* state) } strcpy(fileName, BASEFILENAME); - strcat(fileName, "."); - strcat(fileName, state); + Str_Strcat(fileName, ".", fileNameSize); + Str_Strcat(fileName, state, fileNameSize); fd = open(fileName, O_WRONLY|O_CREAT|O_EXCL, 0644); @@ -659,7 +669,8 @@ Touch(const char* state) static DeployPkgStatus UnTouch(const char* state) { - char* fileName = malloc(strlen(BASEFILENAME) + 1 + strlen(state) + 1); + int fileNameSize = strlen(BASEFILENAME) + 1 + strlen(state) + 1; + char* fileName = malloc(fileNameSize); int result; sLog(log_info, "EXIT STATE %s \n", state); @@ -669,8 +680,8 @@ UnTouch(const char* state) } strcpy(fileName, BASEFILENAME); - strcat(fileName, "."); - strcat(fileName, state); + Str_Strcat(fileName, ".", fileNameSize); + Str_Strcat(fileName, state, fileNameSize); result = remove(fileName); @@ -758,9 +769,10 @@ GetNicsToEnable(const char* dir) FILE *file; char *ret = NULL; - char *fileName = malloc(strlen(dir) + strlen(nicFile) + 1); + int fileNameSize = strlen(dir) + strlen(nicFile) + 1; + char *fileName = malloc(fileNameSize); strcpy(fileName, dir); - strcat(fileName, nicFile); + Str_Strcat(fileName, nicFile, fileNameSize); file = fopen(fileName, "r"); if (file) { @@ -899,14 +911,14 @@ _DeployPkg_SkipReboot(bool skip) * - nics.tx * - cust.cfg to a predefined location. * - * @param [IN] tmpDirPath Path where nics.txt and cust.cfg exist + * @param [IN] imcDirPath Path where nics.txt and cust.cfg exist * @returns DEPLOYPKG_STATUS_CLOUD_INIT_DELEGATED on success * DEPLOYPKG_STATUS_ERROR on error * *---------------------------------------------------------------------------- * */ static DeployPkgStatus -CloudInitSetup(const char *tmpDirPath) +CloudInitSetup(const char *imcDirPath) { DeployPkgStatus deployPkgStatus = DEPLOYPKG_STATUS_ERROR; static const char *cloudInitTmpDirPath = "/var/run/vmware-imc"; @@ -934,7 +946,7 @@ CloudInitSetup(const char *tmpDirPath) // rename in order to avoid race conditions with partial writes. sLog(log_info, "Check if nics.txt exists. Copy if exists, skip otherwise"); snprintf(command, sizeof(command), - "/usr/bin/test -f %s/nics.txt", tmpDirPath); + "/usr/bin/test -f %s/nics.txt", imcDirPath); command[sizeof(command) - 1] = '\0'; forkExecResult = ForkExecAndWaitCommand(command, false); @@ -946,18 +958,19 @@ CloudInitSetup(const char *tmpDirPath) */ if (forkExecResult == 0) { sLog(log_info, "nics.txt file exists. Copying.."); - if (!CopyFileToDirectory(tmpDirPath, cloudInitTmpDirPath, "nics.txt")) { + if (!CopyFileToDirectory(imcDirPath, cloudInitTmpDirPath, "nics.txt")) { goto done; } } // Get custom script name. - if (HasCustomScript(tmpDirPath, &customScriptName)) { + customScriptName = GetCustomScript(imcDirPath); + if (customScriptName != NULL) { char scriptPath[1024]; sLog(log_info, "Custom script present."); sLog(log_info, "Copying script to execute post customization."); - snprintf(scriptPath, sizeof(scriptPath), "%s/scripts", tmpDirPath); + snprintf(scriptPath, sizeof(scriptPath), "%s/scripts", imcDirPath); scriptPath[sizeof(scriptPath) - 1] = '\0'; if (!CopyFileToDirectory(scriptPath, cloudInitTmpDirPath, "post-customize-guest.sh")) { @@ -966,14 +979,14 @@ CloudInitSetup(const char *tmpDirPath) sLog(log_info, "Copying user uploaded custom script %s", customScriptName); - if (!CopyFileToDirectory(tmpDirPath, cloudInitTmpDirPath, + if (!CopyFileToDirectory(imcDirPath, cloudInitTmpDirPath, customScriptName)) { goto done; } } sLog(log_info, "Copying main configuration file cust.cfg"); - if (!CopyFileToDirectory(tmpDirPath, cloudInitTmpDirPath, "cust.cfg")) { + if (!CopyFileToDirectory(imcDirPath, cloudInitTmpDirPath, "cust.cfg")) { goto done; } @@ -1130,28 +1143,52 @@ Deploy(const char* packageName) uint8 archiveType; uint8 flags; bool forceSkipReboot = false; - char *tmpDirPath; + const char *baseDirPath = NULL; + char *imcDirPath = NULL; bool useCloudInitWorkflow = false; - + int imcDirPathSize = 0; + int cleanupCommandSize = 0; TransitionState(NULL, INPROGRESS); // Notify the vpx of customization in-progress state SetCustomizationStatusInVmx(TOOLSDEPLOYPKG_RUNNING, TOOLSDEPLOYPKG_ERROR_SUCCESS, NULL); - tmpDirPath = mkdtemp((char *)Util_SafeStrdup(TMP_DIR_PATH_PATTERN)); - if (tmpDirPath == NULL) { - SetDeployError("Error creating tmp dir: %s", strerror(errno)); + + // PR 2127543, Use /var/run or /run but /tmp firstly + if (File_IsDirectory(VARRUNDIR)) { + baseDirPath = VARRUNDIR; + } else if (File_IsDirectory(RUNDIR)) { + baseDirPath = RUNDIR; + } else { + baseDirPath = TMPDIR; + } + + // Create a random name dir under base dir path + imcDirPathSize = strlen(baseDirPath) + strlen(IMC_DIR_PATH_PATTERN) + 1; + imcDirPath = malloc(imcDirPathSize); + if (imcDirPath == NULL) { + SetDeployError("Error allocating memory to create imc dir."); + return DEPLOYPKG_STATUS_ERROR; + } + strcpy(imcDirPath, baseDirPath); + Str_Strcat(imcDirPath, IMC_DIR_PATH_PATTERN, imcDirPathSize); + if (mkdtemp(imcDirPath) == NULL) { + free(imcDirPath); + SetDeployError("Error creating imc dir: %s", strerror(errno)); return DEPLOYPKG_STATUS_ERROR; } - sLog(log_info, "Reading cabinet file %s. \n", packageName); + sLog(log_info, + "Reading cabinet file %s and will extract it to %s. \n", + packageName, + imcDirPath); // Get the command to execute if (!GetPackageInfo(packageName, &pkgCommand, &archiveType, &flags)) { SetDeployError("Error extracting package header information. (%s)", GetDeployError()); - free(tmpDirPath); + free(imcDirPath); return DEPLOYPKG_STATUS_CAB_ERROR; } @@ -1159,30 +1196,30 @@ Deploy(const char* packageName) sLog(log_info, "Original deployment command: %s\n", pkgCommand); if (strstr(pkgCommand, IMC_TMP_PATH_VAR) != NULL) { - command = StrUtil_ReplaceAll(pkgCommand, IMC_TMP_PATH_VAR, tmpDirPath); + command = StrUtil_ReplaceAll(pkgCommand, IMC_TMP_PATH_VAR, imcDirPath); } else { - command = StrUtil_ReplaceAll(pkgCommand, TMP_PATH_VAR, tmpDirPath); + command = StrUtil_ReplaceAll(pkgCommand, TMP_PATH_VAR, imcDirPath); } free(pkgCommand); sLog(log_info, "Actual deployment command: %s\n", command); if (archiveType == VMWAREDEPLOYPKG_PAYLOAD_TYPE_CAB) { - if (!ExtractCabPackage(packageName, tmpDirPath)) { - free(tmpDirPath); + if (!ExtractCabPackage(packageName, imcDirPath)) { + free(imcDirPath); free(command); return DEPLOYPKG_STATUS_CAB_ERROR; } } else if (archiveType == VMWAREDEPLOYPKG_PAYLOAD_TYPE_ZIP) { - if (!ExtractZipPackage(packageName, tmpDirPath)) { - free(tmpDirPath); + if (!ExtractZipPackage(packageName, imcDirPath)) { + free(imcDirPath); free(command); return DEPLOYPKG_STATUS_CAB_ERROR; } } if (!(flags & VMWAREDEPLOYPKG_HEADER_FLAGS_IGNORE_CLOUD_INIT)) { - useCloudInitWorkflow = UseCloudInitWorkflow(tmpDirPath); + useCloudInitWorkflow = UseCloudInitWorkflow(imcDirPath); } else { sLog(log_info, "Ignoring cloud-init."); } @@ -1191,7 +1228,7 @@ Deploy(const char* packageName) sLog(log_info, "Executing cloud-init workflow"); sSkipReboot = TRUE; free(command); - deployPkgStatus = CloudInitSetup(tmpDirPath); + deployPkgStatus = CloudInitSetup(imcDirPath); } else { sLog(log_info, "Executing traditional GOSC workflow"); deploymentResult = ForkExecAndWaitCommand(command, false); @@ -1224,7 +1261,7 @@ Deploy(const char* packageName) sLog(log_error, "Deployment failed. " "The forked off process returned error code. \n"); } else { - nics = GetNicsToEnable(tmpDirPath); + nics = GetNicsToEnable(imcDirPath); if (nics) { // XXX: Sleep before the last SetCustomizationStatusInVmx // This is a temporary-hack for PR 422790 @@ -1248,24 +1285,24 @@ Deploy(const char* packageName) sLog(log_info, "Deployment succeeded. \n"); } } - - cleanupCommand = malloc(strlen(CLEANUPCMD) + strlen(tmpDirPath) + 1); + cleanupCommandSize = strlen(CLEANUPCMD) + strlen(imcDirPath) + 1; + cleanupCommand = malloc(cleanupCommandSize); if (!cleanupCommand) { SetDeployError("Error allocating memory."); - free(tmpDirPath); + free(imcDirPath); return DEPLOYPKG_STATUS_ERROR; } strcpy(cleanupCommand, CLEANUPCMD); - strcat(cleanupCommand, tmpDirPath); + Str_Strcat(cleanupCommand, imcDirPath, cleanupCommandSize); sLog(log_info, "Launching cleanup. \n"); if (ForkExecAndWaitCommand(cleanupCommand, false) != 0) { - sLog(log_warning, "Error while clean up tmp directory %s: (%s)", - tmpDirPath, strerror (errno)); + sLog(log_warning, "Error while cleaning up imc directory %s: (%s)", + imcDirPath, strerror (errno)); } free (cleanupCommand); - free(tmpDirPath); + free(imcDirPath); if (flags & VMWAREDEPLOYPKG_HEADER_FLAGS_SKIP_REBOOT) { forceSkipReboot = true; diff --git a/open-vm-tools/libDeployPkg/linuxDeploymentUtilities.c b/open-vm-tools/libDeployPkg/linuxDeploymentUtilities.c index 93e1b0aae..8e715e44e 100644 --- a/open-vm-tools/libDeployPkg/linuxDeploymentUtilities.c +++ b/open-vm-tools/libDeployPkg/linuxDeploymentUtilities.c @@ -48,97 +48,100 @@ IsCloudInitEnabled(const char *cloudFilePath) FILE *cloudFile; char line[256]; regex_t regex; - // Expected regex in cloud.cfg file - const char *cloudInitRegex = "^\\s*disable_vmware_customization\\s*:\\s*false\\s*$"; - int reti = regcomp(®ex, cloudInitRegex, 0); - if (reti) { - char buf[256]; - regerror(reti, ®ex, buf, sizeof(buf)); - sLog(log_warning, "Error compiling regex for cloud-init flag: %s", buf); - return isEnabled; - } + const char *cloudInitRegex = + "^\\s*disable_vmware_customization\\s*:\\s*false\\s*$"; + int reti; sLog(log_info, "Checking if cloud.cfg exists and if cloud-init is enabled."); - // Read cloud.cfg file and find expected string. cloudFile = fopen(cloudFilePath, "r"); if (cloudFile == NULL) { sLog(log_info, "Could not open file: %s", strerror(errno)); + return isEnabled; + } + + reti = regcomp(®ex, cloudInitRegex, 0); + if (reti != 0) { + char buf[256]; + regerror(reti, ®ex, buf, sizeof(buf)); + sLog(log_error, "Error compiling regex for cloud-init flag: %s", buf); goto done; } - while(fgets(line, sizeof(line), cloudFile)) { - if (!regexec(®ex, line, 0, NULL, 0)) { + + while (fgets(line, sizeof(line), cloudFile) != NULL) { + if (regexec(®ex, line, 0, NULL, 0) == 0) { isEnabled = true; break; } } - if (ferror(cloudFile)) { + if (ferror(cloudFile) != 0) { sLog(log_warning, "Error reading file: %s", strerror(errno)); isEnabled = false; } - fclose(cloudFile); + regfree(®ex); done: - regfree(®ex); + fclose(cloudFile); return isEnabled; } /** *----------------------------------------------------------------------------- * - * HasCustomScript + * GetCustomScript * - * Get custom script name if it exists. + * Get custom script name if it exists. Returns the first script found. * * @param [IN] dirPath path to extracted cab files - * @param [IN/OUT] scriptName name of the user uploaded custom script. - * scriptName will be set only if custom script - * exists. - * @returns TRUE if custom script exists in dirPath + * + * @returns the script name of the user uploaded custom script if it + * is found in dirPath. Must be freed by caller. + * + * NULL on failure or if the script does not exist * * ---------------------------------------------------------------------------- **/ -bool -HasCustomScript(const char* dirPath, char** scriptName) +char * +GetCustomScript(const char* dirPath) { - bool hasScript = false; - size_t scriptSize; + char *scriptName = NULL; static const char *customScriptRegex = "^script[A-Za-z0-9]*\\.bat"; DIR *tempDir; struct dirent *dir; regex_t scriptRegex; - int ret = regcomp(&scriptRegex, customScriptRegex, 0); - if (ret) { - char buf[256]; - regerror(ret, &scriptRegex, buf, sizeof(buf)); - sLog(log_warning, "Error compiling regex for custom script: %s", - buf); - return hasScript; - } + int regRet; + sLog(log_info, "Check if custom script(pre/post customization) exists."); tempDir = opendir(dirPath); if (tempDir == NULL) { sLog(log_warning, "Could not open directory %s: error: %s", dirPath, strerror(errno)); + return scriptName; + } + + regRet = regcomp(&scriptRegex, customScriptRegex, 0); + if (regRet != 0) { + char buf[256]; + + regerror(regRet, &scriptRegex, buf, sizeof(buf)); + sLog(log_error, "Error compiling regex for custom script: %s", buf); goto done; } + while ((dir = readdir(tempDir)) != NULL) { - if (!regexec(&scriptRegex, dir->d_name, 0, NULL, 0)) { - scriptSize = strlen(dir->d_name); - *scriptName = malloc(sizeof(char) * scriptSize + 1); - if (*scriptName == NULL) { + if (regexec(&scriptRegex, dir->d_name, 0, NULL, 0) == 0) { + scriptName = strdup(dir->d_name); + if (scriptName == NULL) { sLog(log_warning, "Could not allocate memory for scriptName: %s", strerror(errno)); - closedir(tempDir); - goto done; + break; } - **scriptName = '\0'; - strncat(*scriptName, dir->d_name, scriptSize); - hasScript = true; + break; } } - closedir(tempDir); -done: regfree(&scriptRegex); - return hasScript; + +done: + closedir(tempDir); + return scriptName; } diff --git a/open-vm-tools/libDeployPkg/linuxDeploymentUtilities.h b/open-vm-tools/libDeployPkg/linuxDeploymentUtilities.h index e2e6e2374..fd25af807 100644 --- a/open-vm-tools/libDeployPkg/linuxDeploymentUtilities.h +++ b/open-vm-tools/libDeployPkg/linuxDeploymentUtilities.h @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2016-2017 VMware, Inc. All rights reserved. + * Copyright (C) 2016-2018 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published @@ -26,7 +26,7 @@ IMGCUST_API bool IsCloudInitEnabled(const char* configFile); -IMGCUST_API bool -HasCustomScript(const char* dirPath, char** scriptName); +IMGCUST_API char * +GetCustomScript(const char* dirPath); #endif //_LINUXDEPLOYMENTUTILITIES_H_ diff --git a/open-vm-tools/libDeployPkg/mspackWrapper.c b/open-vm-tools/libDeployPkg/mspackWrapper.c index 026df7add..82639d8bf 100644 --- a/open-vm-tools/libDeployPkg/mspackWrapper.c +++ b/open-vm-tools/libDeployPkg/mspackWrapper.c @@ -1,5 +1,5 @@ /********************************************************* - * Copyright (C) 2006-2017 VMware, Inc. All rights reserved. + * Copyright (C) 2006-2018 VMware, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published @@ -32,6 +32,7 @@ #include #include #include +#include "str.h" /* * Template functions @@ -78,6 +79,7 @@ DefaultLog(int logLevel, const char* fmtstr, ...) va_list args; va_start(args, fmtstr); printf(fmtstr, args); + va_end(args); } @@ -183,7 +185,7 @@ ExtractFile (struct mscab_decompressor* deflator, sz = strlen(destDirectory)+ 1 + strlen(fileName)+ 1; { char outCabFile[sz]; - sprintf (outCabFile, "%s/%s", destDirectory, fileName); + Str_Sprintf (outCabFile, sz, "%s/%s", destDirectory, fileName); // set up the path if it does not exist if (SetupPath(outCabFile) != LINUXCAB_SUCCESS) {