lxc_create: prepend pretty header to config file (v2)

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@ubuntu.com>
This commit is contained in:
Serge Hallyn 2013-07-12 14:07:23 -05:00
parent 868a70afea
commit 3ce746862b
4 changed files with 174 additions and 7 deletions

View File

@ -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])])

View File

@ -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:
@ -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;
}

View File

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

View File

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