[lxc-devel] [PATCH 1/1] lxc_create: prepend pretty header to config file

Serge Hallyn serge.hallyn at ubuntu.com
Fri Jul 12 04:51:25 UTC 2013


Define a sha1sum_file() function in utils.c (which requires configure.ac
to check for -lcrypto and -lssl).  Use that in lxcapi_create to write out
the sha1sum of the template being used.

Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>
---
 configure.ac           |    2 +
 src/lxc/Makefile.am    |    2 +-
 src/lxc/lxccontainer.c |  109 ++++++++++++++++++++++++++++++++++++++++++++++--
 src/lxc/utils.c        |   36 ++++++++++++++++
 src/lxc/utils.h        |    2 +
 5 files changed, 146 insertions(+), 5 deletions(-)

diff --git a/configure.ac b/configure.ac
index 4567001..a7de8c8 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([crypto], [EVP_get_digestbyname], [], AC_MSG_ERROR([You must install the ssl and crypto libraries]))
+
 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/Makefile.am b/src/lxc/Makefile.am
index 18469a1..fa090c4 100644
--- a/src/lxc/Makefile.am
+++ b/src/lxc/Makefile.am
@@ -116,7 +116,7 @@ liblxc_so_LDFLAGS = \
 	-shared \
 	-Wl,-soname,liblxc.so.$(firstword $(subst ., ,$(VERSION)))
 
-liblxc_so_LDADD = $(CAP_LIBS) $(APPARMOR_LIBS) $(SECCOMP_LIBS)
+liblxc_so_LDADD = $(CAP_LIBS) $(APPARMOR_LIBS) $(SECCOMP_LIBS) -lssl -lcrypto
 
 bin_SCRIPTS = \
 	lxc-ps \
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 4ff9d35..4b26051 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -862,6 +862,102 @@ static bool create_run_template(struct lxc_container *c, char *tpath,
 	return true;
 }
 
+bool prepend_lxc_header(char *path, const char *t, char *const argv[])
+{
+	size_t flen;
+	char *contents, *tpath;
+	int i, md_len;
+	FILE *f;
+	unsigned char md_value[EVP_MAX_MD_SIZE];
+	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 (tpath) {
+		have_tpath = true;
+		md_len = sha1sum_file(tpath, md_value);
+		free(tpath);
+		if (md_len < 0) {
+			free(contents);
+			return false;
+		}
+	}
+
+	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_tpath) {
+		fprintf(f, "# Template script checksum (SHA-1): ");
+		for (i=0; i<md_len; i++)
+			fprintf(f, "%02x", md_value[i]);
+		fprintf(f, "\n");
+	}
+	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:
@@ -959,6 +1055,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:
@@ -1612,13 +1713,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);
@@ -1628,15 +1729,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..b595d13 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -36,6 +36,7 @@
 #include <libgen.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <openssl/evp.h>
 
 #include "log.h"
 
@@ -392,3 +393,38 @@ int lxc_read_nointr_expect(int fd, void* buf, size_t count, const void* expected
 	}
 	return ret;
 }
+
+int sha1sum_file(char *fnam, unsigned char *md_value)
+{
+	EVP_MD_CTX *mdctx;
+	const EVP_MD *md;
+	char *line = NULL;
+	size_t len = 0, ret;
+	FILE *f;
+
+	unsigned int md_len;
+
+	OpenSSL_add_all_digests();
+	md = EVP_get_digestbyname("sha1");
+	if(!md) {
+		ERROR("Unknown message digest sha1\n");
+		return -1;
+	}
+
+	if ((f = fopen(fnam, "r")) < 0) {
+		SYSERROR("failed to open %s", fnam);
+		return -1;
+	}
+
+	mdctx = EVP_MD_CTX_create();
+	EVP_DigestInit_ex(mdctx, md, NULL);
+
+	while ((ret = getline(&line, &len, f)) != -1)
+		EVP_DigestUpdate(mdctx, line, ret);
+	EVP_DigestFinal_ex(mdctx, md_value, &md_len);
+	EVP_MD_CTX_destroy(mdctx);
+	fclose(f);
+	if (line)
+		free(line);
+	return (int) md_len;
+}
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index 063f76c..ffcd4e5 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -26,6 +26,7 @@
 #include <errno.h>
 #include <sys/types.h>
 #include "config.h"
+#include <openssl/evp.h>
 
 /* returns 1 on success, 0 if there were any failures */
 extern int lxc_rmdir_onedev(char *path);
@@ -176,5 +177,6 @@ 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);
+extern int sha1sum_file(char *fnam, unsigned char *md_value);
 
 #endif
-- 
1.7.9.5





More information about the lxc-devel mailing list