]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Updates to the DeployPkg guest customization source code.
authorOliver Kurth <okurth@vmware.com>
Tue, 18 Dec 2018 22:12:19 +0000 (14:12 -0800)
committerOliver Kurth <okurth@vmware.com>
Tue, 18 Dec 2018 22:12:19 +0000 (14:12 -0800)
open-vm-tools/libDeployPkg/linuxDeployment.c
open-vm-tools/libDeployPkg/linuxDeploymentUtilities.c
open-vm-tools/libDeployPkg/linuxDeploymentUtilities.h
open-vm-tools/libDeployPkg/mspackWrapper.c

index 34c8b956b51fbe00059a39d4a524314643fab749..0c853cda79bc194809dd57f6d5c10aab13e34e8d 100644 (file)
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
+#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 <file.h>
 #include <strutil.h>
 #include <util.h>
 
@@ -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;
index 93e1b0aae62d33c5f8a53648231c2e9b71ef59c1..8e715e44e0944f87ad767cf8bf25bfd70621f843 100644 (file)
@@ -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(&regex, cloudInitRegex, 0);
-   if (reti) {
-      char buf[256];
-      regerror(reti, &regex, 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(&regex, cloudInitRegex, 0);
+   if (reti != 0) {
+      char buf[256];
+      regerror(reti, &regex, 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(&regex, line, 0, NULL, 0)) {
+
+   while (fgets(line, sizeof(line), cloudFile) != NULL) {
+      if (regexec(&regex, 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(&regex);
 
 done:
-   regfree(&regex);
+   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;
 }
 
index e2e6e23745995ad476c6d75dcccb496f83aefb9a..fd25af8079e024cb2061447fbb81386161752f7d 100644 (file)
@@ -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_
 
index 026df7add9c81adc9c75249ad59b5eec923a9f81..82639d8bf6908ebe1de8210271f206a59091d5c2 100644 (file)
@@ -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 <mspack.h>
 #include <stdarg.h>
 #include <errno.h>
+#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) {