open-vm-tools/0001-randomly-generate-tmp-directory-name.patch

421 lines
14 KiB
Diff
Raw Normal View History

From 180dcbd06dd3990a8de3f881ad29cdb29d9ed4a4 Mon Sep 17 00:00:00 2001
From: Oliver Kurth <okurth@vmware.com>
Date: Thu, 6 Jul 2017 17:00:55 -0700
Subject: [PATCH] randomly generate tmp directory name
(cherry picked from commit 22e58289f71232310d30cf162b83b5151a937bac)
---
open-vm-tools/libDeployPkg/linuxDeployment.c | 232 +++++++++++++--------------
1 file changed, 114 insertions(+), 118 deletions(-)
diff --git a/open-vm-tools/libDeployPkg/linuxDeployment.c b/open-vm-tools/libDeployPkg/linuxDeployment.c
index 1c8f7855..8e536a97 100644
--- a/open-vm-tools/libDeployPkg/linuxDeployment.c
+++ b/open-vm-tools/libDeployPkg/linuxDeployment.c
@@ -43,6 +43,8 @@
#include "mspackWrapper.h"
#include "rpcout.h"
#include "toolsDeployPkg.h"
+#include <strutil.h>
+#include <util.h>
/*
* These are covered by #ifndef to give the ability to change these
@@ -52,12 +54,17 @@
#define CLEANUPCMD "/bin/rm -r -f "
-#ifndef EXTRACTPATH
-#define EXTRACTPATH "/tmp/.vmware/linux/deploy"
+#ifndef TMP_PATH_VAR
+#define TMP_PATH_VAR "/tmp/.vmware/linux/deploy"
#endif
-#ifndef CLEANUPPATH
-#define CLEANUPPATH "/tmp/.vmware"
+#ifndef IMC_TMP_PATH_VAR
+#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"
#endif
#ifndef BASEFILENAME
@@ -115,13 +122,14 @@ struct List {
// Private functions
static Bool GetPackageInfo(const char* pkgName, char** cmd, uint8* type, uint8* flags);
static Bool ExtractZipPackage(const char* pkg, const char* dest);
-static Bool CreateDir(const char *path);
static void Init(void);
static struct List* AddToList(struct List* head, const char* token);
static int ListSize(struct List* head);
static int Touch(const char* state);
static int UnTouch(const char* state);
static int TransitionState(const char* stateFrom, const char* stateTo);
+static bool CopyFileToDirectory(const char* srcPath, const char* destPath,
+ const char* fileName);
static int Deploy(const char* pkgName);
static char** GetFormattedCommandLine(const char* command);
static int ForkExecAndWaitCommand(const char* command);
@@ -151,8 +159,17 @@ static LogFunction sLog = NoLogging;
NORETURN void
Panic(const char *fmtstr, ...)
{
- /* Ignored */
- sLog(log_warning, "Panic callback invoked. \n");
+ va_list args;
+
+ char *tmp = Util_SafeMalloc(MAXSTRING);
+
+ va_start(args, fmtstr);
+ vsprintf(tmp, fmtstr, args);
+
+ sLog(log_error, "Panic callback invoked: %s\n", tmp);
+
+ free(tmp);
+
exit(1);
}
@@ -169,12 +186,19 @@ Panic(const char *fmtstr, ...)
*
**/
void
-Debug(const char *fmtstr,
- va_list args)
+Debug(const char *fmtstr, ...)
{
- /* Ignored */
#ifdef VMX86_DEBUG
- sLog(log_warning, "Debug callback invoked. \n");
+ va_list args;
+
+ char *tmp = Util_SafeMalloc(MAXSTRING);
+
+ va_start(args, fmtstr);
+ vsprintf(tmp, fmtstr, args);
+
+ sLog(log_debug, "Debug callback invoked: %s\n", tmp);
+
+ free(tmp);
#endif
}
@@ -874,11 +898,13 @@ static int
CloudInitSetup(const char *tmpDirPath)
{
int deployStatus = DEPLOY_ERROR;
- const char *cloudInitTmpDirPath = "/var/run/vmware-imc";
+ static const char *cloudInitTmpDirPath = "/var/run/vmware-imc";
int forkExecResult;
char command[1024];
Bool cloudInitTmpDirCreated = FALSE;
+ sLog(log_info, "Creating temp directory %s to copy customization files",
+ cloudInitTmpDirPath);
snprintf(command, sizeof(command),
"/bin/mkdir -p %s", cloudInitTmpDirPath);
command[sizeof(command) - 1] = '\0';
@@ -893,26 +919,9 @@ CloudInitSetup(const char *tmpDirPath)
cloudInitTmpDirCreated = TRUE;
- snprintf(command, sizeof(command),
- "/bin/rm -f %s/cust.cfg %s/nics.txt",
- cloudInitTmpDirPath, cloudInitTmpDirPath);
- command[sizeof(command) - 1] = '\0';
-
- forkExecResult = ForkExecAndWaitCommand(command);
-
- snprintf(command, sizeof(command),
- "/bin/cp %s/cust.cfg %s/cust.cfg",
- tmpDirPath, cloudInitTmpDirPath);
- command[sizeof(command) - 1] = '\0';
-
- forkExecResult = ForkExecAndWaitCommand(command);
-
- if (forkExecResult != 0) {
- SetDeployError("Error copying cust.cfg file: %s",
- strerror(errno));
- goto done;
- }
-
+ // Copy required files for cloud-init to a temp name initially and then
+ // 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);
command[sizeof(command) - 1] = '\0';
@@ -925,26 +934,27 @@ CloudInitSetup(const char *tmpDirPath)
* We need to copy the nics.txt only if it exists.
*/
if (forkExecResult == 0) {
- snprintf(command, sizeof(command),
- "/bin/cp %s/nics.txt %s/nics.txt",
- tmpDirPath, cloudInitTmpDirPath);
- command[sizeof(command) - 1] = '\0';
-
- forkExecResult = ForkExecAndWaitCommand(command);
- if (forkExecResult != 0) {
- SetDeployError("Error copying nics.txt file: %s",
- strerror(errno));
+ sLog(log_info, "nics.txt file exists. Copying..");
+ if(!CopyFileToDirectory(tmpDirPath, cloudInitTmpDirPath, "nics.txt")) {
goto done;
- }
+ }
+ }
+
+ sLog(log_info, "Copying main configuration file cust.cfg");
+ if(!CopyFileToDirectory(tmpDirPath, cloudInitTmpDirPath, "cust.cfg")) {
+ goto done;
}
deployStatus = DEPLOY_SUCCESS;
done:
if (DEPLOY_SUCCESS == deployStatus) {
+ sLog(log_info, "Deployment for cloud-init succeeded.");
TransitionState(INPROGRESS, DONE);
} else {
+ sLog(log_error, "Deployment for cloud-init failed.");
if (cloudInitTmpDirCreated) {
+ sLog(log_info, "Removing temporary folder %s", cloudInitTmpDirPath);
snprintf(command, sizeof(command),
"/bin/rm -rf %s",
cloudInitTmpDirPath);
@@ -964,6 +974,34 @@ done:
//......................................................................................
+static bool
+CopyFileToDirectory(const char* srcPath, const char* destPath,
+ const char* fileName)
+{
+ char command[1024];
+ int forkExecResult;
+ snprintf(command, sizeof(command), "/bin/cp %s/%s %s/%s.tmp", srcPath,
+ fileName, destPath, fileName);
+ command[sizeof(command) - 1] = '\0';
+ forkExecResult = ForkExecAndWaitCommand(command);
+ if (forkExecResult != 0) {
+ SetDeployError("Error while copying file %s: %s", fileName,
+ strerror(errno));
+ return false;
+ }
+ snprintf(command, sizeof(command), "/bin/mv -f %s/%s.tmp %s/%s", destPath,
+ fileName, destPath, fileName);
+ command[sizeof(command) - 1] = '\0';
+
+ forkExecResult = ForkExecAndWaitCommand(command);
+ if (forkExecResult != 0) {
+ SetDeployError("Error while renaming temp file %s: %s", fileName,
+ strerror(errno));
+ return false;
+ }
+ return true;
+}
+
/**
*
* Core function which takes care of deployment in Linux.
@@ -979,6 +1017,7 @@ static int
Deploy(const char* packageName)
{
int deployStatus = DEPLOY_SUCCESS;
+ char* pkgCommand = NULL;
char* command = NULL;
int deploymentResult = 0;
char *nics;
@@ -986,6 +1025,7 @@ Deploy(const char* packageName)
uint8 archiveType;
uint8 flags;
bool forceSkipReboot = false;
+ char *tmpDirPath;
Bool cloudInitEnabled = FALSE;
const char *cloudInitConfigFilePath = "/etc/cloud/cloud.cfg";
char cloudCommand[1024];
@@ -998,52 +1038,62 @@ Deploy(const char* packageName)
TOOLSDEPLOYPKG_ERROR_SUCCESS,
NULL);
+ tmpDirPath = mkdtemp((char *)Util_SafeStrdup(TMP_DIR_PATH_PATTERN));
+ if (tmpDirPath == NULL) {
+ SetDeployError("Error creating tmp dir: %s", strerror(errno));
+ return DEPLOY_ERROR;
+ }
+
sLog(log_info, "Reading cabinet file %s. \n", packageName);
// Get the command to execute
- if (!GetPackageInfo(packageName, &command, &archiveType, &flags)) {
+ if (!GetPackageInfo(packageName, &pkgCommand, &archiveType, &flags)) {
SetDeployError("Error extracting package header information. (%s)",
GetDeployError());
+ free(tmpDirPath);
return DEPLOY_ERROR;
}
- // Print the header command
-#ifdef VMX86_DEBUG
- sLog(log_debug, "Header command: %s \n ", command);
-#endif
-
- // create the destination directory
- if (!CreateDir(EXTRACTPATH "/")) {
- free(command);
- return DEPLOY_ERROR;
+ 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);
+ } else {
+ command = StrUtil_ReplaceAll(pkgCommand, TMP_PATH_VAR, tmpDirPath);
}
+ free(pkgCommand);
+
+ sLog(log_info, "Actual deployment command: %s\n", command);
if (archiveType == VMWAREDEPLOYPKG_PAYLOAD_TYPE_CAB) {
- if (!ExtractCabPackage(packageName, EXTRACTPATH)) {
+ if (!ExtractCabPackage(packageName, tmpDirPath)) {
+ free(tmpDirPath);
free(command);
return DEPLOY_ERROR;
}
} else if (archiveType == VMWAREDEPLOYPKG_PAYLOAD_TYPE_ZIP) {
- if (!ExtractZipPackage(packageName, EXTRACTPATH)) {
+ if (!ExtractZipPackage(packageName, tmpDirPath)) {
+ free(tmpDirPath);
free(command);
return DEPLOY_ERROR;
}
}
// check if cloud-init installed
+ sLog(log_info, "Checking if cloud-init is installed");
snprintf(cloudCommand, sizeof(cloudCommand),
"/usr/bin/cloud-init -h");
cloudCommand[sizeof(cloudCommand) - 1] = '\0';
forkExecResult = ForkExecAndWaitCommand(cloudCommand);
// if cloud-init is installed, check if it is enabled
if (forkExecResult == 0 && IsCloudInitEnabled(cloudInitConfigFilePath)) {
+ sLog(log_info, "cloud-init is installed and enabled");
cloudInitEnabled = TRUE;
sSkipReboot = TRUE;
free(command);
- deployStatus = CloudInitSetup(EXTRACTPATH);
+ deployStatus = CloudInitSetup(tmpDirPath);
} else {
- // Run the deployment command
- sLog(log_info, "Launching deployment %s. \n", command);
+ sLog(log_info, "cloud-init is either not installed or the flag to enable \
+ cloud-init is not set.\n Executing traditional GOSC workflow");
deploymentResult = ForkExecAndWaitCommand(command);
free(command);
@@ -1089,7 +1139,7 @@ Deploy(const char* packageName)
* of the sucess/failure of the customization so that at the end of it we
* always have nics enabled.
*/
- nics = GetNicsToEnable(EXTRACTPATH);
+ nics = GetNicsToEnable(tmpDirPath);
if (nics) {
// XXX: Sleep before the last SetCustomizationStatusInVmx
// This is a temporary-hack for PR 422790
@@ -1104,22 +1154,23 @@ Deploy(const char* packageName)
}
}
- cleanupCommand = malloc(strlen(CLEANUPCMD) + strlen(CLEANUPPATH) + 1);
+ cleanupCommand = malloc(strlen(CLEANUPCMD) + strlen(tmpDirPath) + 1);
if (!cleanupCommand) {
SetDeployError("Error allocating memory.");
+ free(tmpDirPath);
return DEPLOY_ERROR;
}
strcpy(cleanupCommand, CLEANUPCMD);
- strcat(cleanupCommand, CLEANUPPATH);
+ strcat(cleanupCommand, tmpDirPath);
sLog(log_info, "Launching cleanup. \n");
if (ForkExecAndWaitCommand(cleanupCommand) != 0) {
- sLog(log_warning, "Error while clean up. Error removing directory %s. (%s)",
- EXTRACTPATH, strerror (errno));
- //TODO: What should be done if cleanup fails ??
+ sLog(log_warning, "Error while clean up tmp directory %s: (%s)",
+ tmpDirPath, strerror (errno));
}
free (cleanupCommand);
+ free(tmpDirPath);
if (flags & VMWAREDEPLOYPKG_HEADER_FLAGS_SKIP_REBOOT) {
forceSkipReboot = true;
@@ -1388,61 +1439,6 @@ ForkExecAndWaitCommand(const char* command)
return retval;
}
-/**
- * Sets up the path for exracting file. For e.g. if the file is /a/b/c/d.abc
- * then it creates /a/b/c (skips if any of the directories along the path
- * exists). If the the path ends in '/', then the the entire input is assumed
- * to be a directory and is created as such.
- *
- * @param path IN: Complete path of the file
- * @return TRUE on success
- */
-
-Bool
-CreateDir(const char* path)
-{
- struct stat stats;
- char* token;
- char* copy;
-
- // make a copy we can modify
- copy = strdup(path);
-
- // walk through the path (it employs in string replacement)
- for (token = copy + 1; *token; ++token) {
-
- // find
- if (*token != '/') {
- continue;
- }
-
- /*
- * cut it off here for e.g. on first iteration /a/b/c/d.abc will have
- * token /a, on second /a/b etc
- */
- *token = 0;
-
- sLog(log_debug, "Creating directory %s", copy);
-
- // ignore if the directory exists
- if (!((stat(copy, &stats) == 0) && S_ISDIR(stats.st_mode))) {
- // make directory and check error (accessible only by owner)
- if (mkdir(copy, 0700) == -1) {
- sLog(log_error, "Unable to create directory %s (%s)", copy,
- strerror(errno));
- free(copy);
- return FALSE;
- }
- }
-
- // restore the token
- *token = '/';
- }
-
- free(copy);
- return TRUE;
-}
-
//......................................................................................
/**
--
2.13.2