diff --git a/configure.ac b/configure.ac index 456700185..56638d4ee 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 446827c0a..0c13e0682 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; ilxc_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: @@ -1623,13 +1729,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); @@ -1639,15 +1745,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 136f943a1..c3f734b05 100644 --- a/src/lxc/utils.c +++ b/src/lxc/utils.c @@ -37,6 +37,7 @@ #include #include +#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 +#include +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 063f76cce..14b8439d4 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