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

Stéphane Graber stgraber at ubuntu.com
Fri Jul 12 13:50:51 UTC 2013


On Thu, Jul 11, 2013 at 11:51:25PM -0500, Serge Hallyn wrote:
> 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(-)

Does the LXC license allow linking to OpenSSL?

Specifically we need the following bit in the license:
 * In addition, as a special exception, the copyright holders give
 * permission to link the code of portions of this program with the
 * OpenSSL library under certain conditions as described in each
 * individual source file, and distribute linked combinations
 * including the two.
 * You must obey the GNU General Public License in all respects
 * for all of the code used other than OpenSSL.  If you modify
 * file(s) with this exception, you may extend this exception to your
 * version of the file(s), but you are not obligated to do so.  If you
 * do not wish to do so, delete this exception statement from your
 * version.  If you delete this exception statement from all source
 * files in the program, then also delete it here.

Details: https://people.gnome.org/~markmc/openssl-and-the-gpl.html

> 
> 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
> 

-- 
Stéphane Graber
Ubuntu developer
http://www.ubuntu.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20130712/d5041b4b/attachment.pgp>


More information about the lxc-devel mailing list