]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
lxccontainer: do_lxcapi_save_config()
authorChristian Brauner <christian.brauner@ubuntu.com>
Fri, 23 Feb 2018 14:43:50 +0000 (15:43 +0100)
committerChristian Brauner <christian.brauner@ubuntu.com>
Sat, 24 Feb 2018 20:38:02 +0000 (21:38 +0100)
If liblxc is used multi-threaded do_lxcapi_save_config() could be called from
threads that fork() which to not risk ending up with invalid locking states we
should avoid using functions like fopen() that internally allocate memory and
use locking. Let's replace it with the async-signal safe combination of
open() + write().

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/confile.c
src/lxc/confile.h
src/lxc/lxccontainer.c

index effff93dd385a0f9530cf8334c024cb925b248ed..8c3eccccc7427fa93bfc49f9ec6e28a38564502e 100644 (file)
@@ -2417,17 +2417,21 @@ signed long lxc_config_parse_arch(const char *arch)
 }
 
 /* Write out a configuration file. */
-void write_config(FILE *fout, struct lxc_conf *c)
+int write_config(int fd, const struct lxc_conf *conf)
 {
        int ret;
-       size_t len = c->unexpanded_len;
+       size_t len = conf->unexpanded_len;
 
-       if (!len)
-               return;
+       if (len == 0)
+               return 0;
 
-       ret = fwrite(c->unexpanded_config, 1, len, fout);
-       if (ret != len)
+       ret = lxc_write_nointr(fd, conf->unexpanded_config, len);
+       if (ret < 0) {
                SYSERROR("Failed to write configuration file");
+               return -1;
+       }
+
+       return 0;
 }
 
 bool do_append_unexp_config_line(struct lxc_conf *conf, const char *key,
index c8929658ed3e6ab4c3795a3f82956eee0843b54b..0d877c898048f50f2aa87d9673fc6d40980886c4 100644 (file)
@@ -93,7 +93,7 @@ extern signed long lxc_config_parse_arch(const char *arch);
 
 extern int lxc_clear_config_item(struct lxc_conf *c, const char *key);
 
-extern void write_config(FILE *fout, struct lxc_conf *c);
+extern int write_config(int fd, const struct lxc_conf *conf);
 
 extern bool do_append_unexp_config_line(struct lxc_conf *conf, const char *key,
                                        const char *v);
index 4b056b6b088f84ba3c4858f24ddf83497f97a914..1c9d2b169b22fdc226dca81fb2b884dd315fc2be 100644 (file)
@@ -2418,9 +2418,8 @@ WRAP_API_3(int, lxcapi_get_keys, const char *, char *, int)
 
 static bool do_lxcapi_save_config(struct lxc_container *c, const char *alt_file)
 {
-       FILE *fout;
+       int fd, lret;
        bool ret = false, need_disklock = false;
-       int lret;
 
        if (!alt_file)
                alt_file = c->configfile;
@@ -2430,7 +2429,10 @@ static bool do_lxcapi_save_config(struct lxc_container *c, const char *alt_file)
        /* If we haven't yet loaded a config, load the stock config. */
        if (!c->lxc_conf) {
                if (!do_lxcapi_load_config(c, lxc_global_config_value("lxc.default_config"))) {
-                       ERROR("Error loading default configuration file %s while saving %s", lxc_global_config_value("lxc.default_config"), c->name);
+                       ERROR("Error loading default configuration file %s "
+                             "while saving %s",
+                             lxc_global_config_value("lxc.default_config"),
+                             c->name);
                        return false;
                }
        }
@@ -2453,18 +2455,24 @@ static bool do_lxcapi_save_config(struct lxc_container *c, const char *alt_file)
        if (lret)
                return false;
 
-       fout = fopen(alt_file, "w");
-       if (!fout)
-               goto out;
-       write_config(fout, c->lxc_conf);
-       fclose(fout);
+       fd = open(alt_file, O_WRONLY | O_CREAT | O_CLOEXEC,
+                 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
+       if (fd < 0)
+               goto on_error;
+
+       lret = write_config(fd, c->lxc_conf);
+       close(fd);
+       if (lret < 0)
+               goto on_error;
+
        ret = true;
 
-out:
+on_error:
        if (need_disklock)
                container_disk_unlock(c);
        else
                container_mem_unlock(c);
+
        return ret;
 }
 
@@ -3515,10 +3523,9 @@ static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char
                char **hookargs)
 {
        char newpath[MAXPATHLEN];
-       int ret;
+       int fd, ret;
        struct clone_update_data data;
        size_t saved_unexp_len;
-       FILE *fout;
        pid_t pid;
        int storage_copied = 0;
        char *origroot = NULL, *saved_unexp_conf = NULL;
@@ -3562,9 +3569,11 @@ static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char
                origroot = c->lxc_conf->rootfs.path;
                c->lxc_conf->rootfs.path = NULL;
        }
-       fout = fopen(newpath, "w");
-       if (!fout) {
-               SYSERROR("open %s", newpath);
+
+       fd = open(newpath, O_WRONLY | O_CREAT | O_CLOEXEC,
+                 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
+       if (fd < 0) {
+               SYSERROR("Failed to open \"%s\"", newpath);
                goto out;
        }
 
@@ -3572,14 +3581,13 @@ static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char
        saved_unexp_len = c->lxc_conf->unexpanded_len;
        c->lxc_conf->unexpanded_config = strdup(saved_unexp_conf);
        if (!c->lxc_conf->unexpanded_config) {
-               ERROR("Out of memory");
-               fclose(fout);
+               close(fd);
                goto out;
        }
 
        clear_unexp_config_line(c->lxc_conf, "lxc.rootfs.path", false);
-       write_config(fout, c->lxc_conf);
-       fclose(fout);
+       write_config(fd, c->lxc_conf);
+       close(fd);
        c->lxc_conf->rootfs.path = origroot;
        free(c->lxc_conf->unexpanded_config);
        c->lxc_conf->unexpanded_config = saved_unexp_conf;