[lxc-devel] [PATCH] lxc_create: prepend pretty header to config file (v2)

Serge Hallyn serge.hallyn at ubuntu.com
Fri Jul 12 19:07:23 UTC 2013


Define a sha1sum_file() function in utils.c.  Use that in lxcapi_create
to write out the sha1sum of the template being used.  If libgnutls is
not found, then the template sha1sum simply won't be printed into the
container config.

This patch also trivially fixes some cases where SYSERROR is used after
a fclose (masking errno) and missing consts in mkdir_p.

Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>
---
 configure.ac           |    2 +
 src/lxc/lxccontainer.c |  114 ++++++++++++++++++++++++++++++++++++++++++++++--
 src/lxc/utils.c        |   61 ++++++++++++++++++++++++--
 src/lxc/utils.h        |    4 ++
 4 files changed, 174 insertions(+), 7 deletions(-)

diff --git a/configure.ac b/configure.ac
index 4567001..56638d4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -105,6 +105,8 @@ if test "$enable_apparmor" = "check" ; then
 fi
 AM_CONDITIONAL([ENABLE_APPARMOR], [test "x$enable_apparmor" = "xyes"])
 
+AC_CHECK_LIB([gnutls], [gnutls_hash_fast])
+
 AM_COND_IF([ENABLE_APPARMOR],
 	[AC_CHECK_HEADER([sys/apparmor.h],[],[AC_MSG_ERROR([You must install the AppArmor development package in order to compile lxc])])
 	AC_CHECK_LIB([apparmor], [aa_change_profile],[],[AC_MSG_ERROR([You must install the AppArmor development package in order to compile lxc])])
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index e578510..b52c17c 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -870,6 +870,107 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool quiet
 	return true;
 }
 
+bool prepend_lxc_header(char *path, const char *t, char *const argv[])
+{
+	size_t flen;
+	char *contents, *tpath;
+	int i, ret;
+	FILE *f;
+	unsigned char md_value[SHA_DIGEST_LENGTH];
+	bool have_tpath = false;
+
+	if ((f = fopen(path, "r")) == NULL) {
+		SYSERROR("Opening old config");
+		return false;
+	}
+	if (fseek(f, 0, SEEK_END) < 0) {
+		SYSERROR("Seeking to end of old config file");
+		fclose(f);
+		return false;
+	}
+	if ((flen = ftell(f)) < 0) {
+		SYSERROR("telling size of old config");
+		fclose(f);
+		return false;
+	}
+	if (fseek(f, 0, SEEK_SET) < 0) {
+		SYSERROR("rewinding old config");
+		fclose(f);
+		return false;
+	}
+	if ((contents = malloc(flen + 1)) == NULL) {
+		SYSERROR("out of memory");
+		fclose(f);
+		return false;
+	}
+	if (fread(contents, 1, flen, f) != flen) {
+		SYSERROR("Reading old config");
+		free(contents);
+		fclose(f);
+		return false;
+	}
+	contents[flen] = '\0';
+	if (fclose(f) < 0) {
+		SYSERROR("closing old config");
+		free(contents);
+		return false;
+	}
+
+	if ((tpath = get_template_path(t)) < 0) {
+		ERROR("bad template: %s\n", t);
+		free(contents);
+		return false;
+	}
+
+#if HAVE_LIBGNUTLS
+	if (tpath) {
+		have_tpath = true;
+		ret = sha1sum_file(tpath, md_value);
+		if (ret < 0) {
+			ERROR("Error getting sha1sum of %s", tpath);
+			free(contents);
+			return false;
+		}
+		free(tpath);
+	}
+#endif
+
+	if ((f = fopen(path, "w")) == NULL) {
+		SYSERROR("reopening config for writing");
+		free(contents);
+		return false;
+	}
+	fprintf(f, "# Template used to create this container: %s\n", t);
+	if (argv) {
+		fprintf(f, "# Parameters passed to the template:");
+		while (*argv) {
+			fprintf(f, " %s", *argv);
+			argv++;
+		}
+		fprintf(f, "\n");
+	}
+#if HAVE_LIBGNUTLS
+	if (have_tpath) {
+		fprintf(f, "# Template script checksum (SHA-1): ");
+		for (i=0; i<SHA_DIGEST_LENGTH; i++)
+			fprintf(f, "%02x", md_value[i]);
+		fprintf(f, "\n");
+	}
+#endif
+	if (fwrite(contents, 1, flen, f) != flen) {
+		SYSERROR("Writing original contents");
+		free(contents);
+		fclose(f);
+		return false;
+	}
+	free(contents);
+	if (fclose(f) < 0) {
+		SYSERROR("Closing config file after write");
+		return false;
+	}
+	return true;
+}
+
 static bool lxcapi_destroy(struct lxc_container *c);
 /*
  * lxcapi_create:
@@ -967,6 +1068,11 @@ static bool lxcapi_create(struct lxc_container *c, const char *t,
 	if (c->lxc_conf)
 		lxc_conf_free(c->lxc_conf);
 	c->lxc_conf = NULL;
+
+	if (!prepend_lxc_header(c->configfile, tpath, argv)) {
+		ERROR("Error prepending header to configuration file");
+		goto out_unlock;
+	}
 	bret = load_config_locked(c, c->configfile);
 
 out_unlock:
@@ -1620,13 +1726,13 @@ static int update_name_and_paths(const char *path, struct lxc_container *oldc,
 	}
 	flen = ftell(f);
 	if (flen < 0) {
-		fclose(f);
 		SYSERROR("telling size of old config");
+		fclose(f);
 		return -1;
 	}
 	if (fseek(f, 0, SEEK_SET) < 0) {
-		fclose(f);
 		SYSERROR("rewinding old config");
+		fclose(f);
 		return -1;
 	}
 	contents = malloc(flen+1);
@@ -1636,15 +1742,15 @@ static int update_name_and_paths(const char *path, struct lxc_container *oldc,
 		return -1;
 	}
 	if (fread(contents, 1, flen, f) != flen) {
+		SYSERROR("reading old config");
 		free(contents);
 		fclose(f);
-		SYSERROR("reading old config");
 		return -1;
 	}
 	contents[flen] = '\0';
 	if (fclose(f) < 0) {
-		free(contents);
 		SYSERROR("closing old config");
+		free(contents);
 		return -1;
 	}
 
diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index 136f943..c3f734b 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -37,6 +37,7 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 
+#include "utils.h"
 #include "log.h"
 
 lxc_log_define(lxc_utils, lxc);
@@ -173,10 +174,10 @@ extern int get_u16(unsigned short *val, const char *arg, int base)
 	return 0;
 }
 
-extern int mkdir_p(char *dir, mode_t mode)
+extern int mkdir_p(const char *dir, mode_t mode)
 {
-	char *tmp = dir;
-	char *orig = dir;
+	const char *tmp = dir;
+	const char *orig = dir;
 	char *makeme;
 
 	do {
@@ -392,3 +393,57 @@ int lxc_read_nointr_expect(int fd, void* buf, size_t count, const void* expected
 	}
 	return ret;
 }
+
+#if HAVE_LIBGNUTLS
+#include <gnutls/gnutls.h>
+#include <gnutls/crypto.h>
+int sha1sum_file(char *fnam, unsigned char *digest)
+{
+	char *buf;
+	int ret;
+	FILE *f;
+	long flen;
+
+	if (!fnam)
+		return -1;
+	if ((f = fopen(fnam, "r")) < 0) {
+		SYSERROR("Error opening template");
+		return -1;
+	}
+	if (fseek(f, 0, SEEK_END) < 0) {
+		SYSERROR("Error seeking to end of template");
+		fclose(f);
+		return -1;
+	}
+	if ((flen = ftell(f)) < 0) {
+		SYSERROR("Error telling size of template");
+		fclose(f);
+		return -1;
+	}
+	if (fseek(f, 0, SEEK_SET) < 0) {
+		SYSERROR("Error seeking to start of template");
+		fclose(f);
+		return -1;
+	}
+	if ((buf = malloc(flen+1)) == NULL) {
+		SYSERROR("Out of memory");
+		fclose(f);
+		return -1;
+	}
+	if (fread(buf, 1, flen, f) != flen) {
+		SYSERROR("Failure reading template");
+		free(buf);
+		fclose(f);
+		return -1;
+	}
+	if (fclose(f) < 0) {
+		SYSERROR("Failre closing template");
+		free(buf);
+		return -1;
+	}
+	buf[flen] = '\0';
+	ret = gnutls_hash_fast(GNUTLS_DIG_SHA1, buf, flen, (void *)digest);
+	free(buf);
+	return ret;
+}
+#endif
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index 063f76c..14b8439 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -176,5 +176,9 @@ extern int lxc_wait_for_pid_status(pid_t pid);
 extern int lxc_write_nointr(int fd, const void* buf, size_t count);
 extern int lxc_read_nointr(int fd, void* buf, size_t count);
 extern int lxc_read_nointr_expect(int fd, void* buf, size_t count, const void* expected_buf);
+#if HAVE_LIBGNUTLS
+#define SHA_DIGEST_LENGTH 20
+extern int sha1sum_file(char *fnam, unsigned char *md_value);
+#endif
 
 #endif
-- 
1.7.9.5





More information about the lxc-devel mailing list