From ed586164105039c1c5b1e6da71f9a6c1ba82adf8 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Wed, 25 Mar 2020 12:46:02 +0100 Subject: [PATCH 1/5] lxc_init: move main() down Signed-off-by: Christian Brauner --- src/lxc/cmd/lxc_init.c | 189 ++++++++++++++++++++--------------------- 1 file changed, 93 insertions(+), 96 deletions(-) diff --git a/src/lxc/cmd/lxc_init.c b/src/lxc/cmd/lxc_init.c index 10fe64f2bb..24f67f0813 100644 --- a/src/lxc/cmd/lxc_init.c +++ b/src/lxc/cmd/lxc_init.c @@ -70,9 +70,6 @@ struct arguments { int argc; }; -static int arguments_parse(struct arguments *my_args, int argc, - char *const argv[]); - static struct arguments my_args = { .options = long_options, .shortopts = short_options @@ -191,6 +188,99 @@ static void remove_self(void) return; } +__noreturn static void print_usage_exit(const struct option longopts[]) + +{ + fprintf(stderr, "Usage: lxc-init [-n|--name=NAME] [-h|--help] [--usage] [--version]\n\ + [-q|--quiet] [-P|--lxcpath=LXCPATH]\n"); + exit(EXIT_SUCCESS); +} + +__noreturn static void print_version_exit(void) +{ + printf("%s\n", LXC_VERSION); + exit(EXIT_SUCCESS); +} + +static void print_help(void) +{ + fprintf(stderr, "\ +Usage: lxc-init --name=NAME -- COMMAND\n\ +\n\ + lxc-init start a COMMAND as PID 2 inside a container\n\ +\n\ +Options :\n\ + -n, --name=NAME NAME of the container\n\ + -q, --quiet Don't produce any output\n\ + -P, --lxcpath=PATH Use specified container path\n\ + -?, --help Give this help list\n\ + --usage Give a short usage message\n\ + --version Print the version number\n\ +\n\ +Mandatory or optional arguments to long options are also mandatory or optional\n\ +for any corresponding short options.\n\ +\n\ +See the lxc-init man page for further information.\n\n"); +} + +static int arguments_parse(struct arguments *args, int argc, + char *const argv[]) +{ + for (;;) { + int c; + int index = 0; + + c = getopt_long(argc, argv, args->shortopts, args->options, &index); + if (c == -1) + break; + switch (c) { + case 'n': + args->name = optarg; + break; + case 'o': + break; + case 'l': + break; + case 'q': + args->quiet = true; + break; + case 'P': + remove_trailing_slashes(optarg); + args->lxcpath = optarg; + break; + case OPT_USAGE: + print_usage_exit(args->options); + case OPT_VERSION: + print_version_exit(); + case '?': + print_help(); + exit(EXIT_FAILURE); + case 'h': + print_help(); + exit(EXIT_SUCCESS); + } + } + + /* + * Reclaim the remaining command arguments + */ + args->argv = &argv[optind]; + args->argc = argc - optind; + + /* If no lxcpath was given, use default */ + if (!args->lxcpath) + args->lxcpath = lxc_global_config_value("lxc.lxcpath"); + + /* Check the command options */ + if (!args->name) { + if (!args->quiet) + fprintf(stderr, "lxc-init: missing container name, use --name option\n"); + return -1; + } + + return 0; +} + int main(int argc, char *argv[]) { int i, logfd, ret; @@ -426,96 +516,3 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); exit(exit_with); } - -__noreturn static void print_usage_exit(const struct option longopts[]) - -{ - fprintf(stderr, "Usage: lxc-init [-n|--name=NAME] [-h|--help] [--usage] [--version]\n\ - [-q|--quiet] [-P|--lxcpath=LXCPATH]\n"); - exit(EXIT_SUCCESS); -} - -__noreturn static void print_version_exit(void) -{ - printf("%s\n", LXC_VERSION); - exit(EXIT_SUCCESS); -} - -static void print_help(void) -{ - fprintf(stderr, "\ -Usage: lxc-init --name=NAME -- COMMAND\n\ -\n\ - lxc-init start a COMMAND as PID 2 inside a container\n\ -\n\ -Options :\n\ - -n, --name=NAME NAME of the container\n\ - -q, --quiet Don't produce any output\n\ - -P, --lxcpath=PATH Use specified container path\n\ - -?, --help Give this help list\n\ - --usage Give a short usage message\n\ - --version Print the version number\n\ -\n\ -Mandatory or optional arguments to long options are also mandatory or optional\n\ -for any corresponding short options.\n\ -\n\ -See the lxc-init man page for further information.\n\n"); -} - -static int arguments_parse(struct arguments *args, int argc, - char *const argv[]) -{ - for (;;) { - int c; - int index = 0; - - c = getopt_long(argc, argv, args->shortopts, args->options, &index); - if (c == -1) - break; - switch (c) { - case 'n': - args->name = optarg; - break; - case 'o': - break; - case 'l': - break; - case 'q': - args->quiet = true; - break; - case 'P': - remove_trailing_slashes(optarg); - args->lxcpath = optarg; - break; - case OPT_USAGE: - print_usage_exit(args->options); - case OPT_VERSION: - print_version_exit(); - case '?': - print_help(); - exit(EXIT_FAILURE); - case 'h': - print_help(); - exit(EXIT_SUCCESS); - } - } - - /* - * Reclaim the remaining command arguments - */ - args->argv = &argv[optind]; - args->argc = argc - optind; - - /* If no lxcpath was given, use default */ - if (!args->lxcpath) - args->lxcpath = lxc_global_config_value("lxc.lxcpath"); - - /* Check the command options */ - if (!args->name) { - if (!args->quiet) - fprintf(stderr, "lxc-init: missing container name, use --name option\n"); - return -1; - } - - return 0; -} From 591f6f44a72d87956c60681294dccf15e2f502da Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Wed, 25 Mar 2020 12:53:13 +0100 Subject: [PATCH 2/5] lxc_init: add missing O_CLOEXEC Signed-off-by: Christian Brauner --- src/lxc/cmd/lxc_init.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lxc/cmd/lxc_init.c b/src/lxc/cmd/lxc_init.c index 24f67f0813..a52793343a 100644 --- a/src/lxc/cmd/lxc_init.c +++ b/src/lxc/cmd/lxc_init.c @@ -87,7 +87,8 @@ static void prevent_forking(void) return; while (getline(&line, &len, f) != -1) { - int fd, ret; + __do_close int fd = -EBADF; + int ret; char *p, *p2; p = strchr(line, ':'); @@ -118,7 +119,7 @@ static void prevent_forking(void) return; } - fd = open(path, O_WRONLY); + fd = open(path, O_WRONLY | O_CLOEXEC); if (fd < 0) { if (my_args.quiet) fprintf(stderr, "Failed to open \"%s\"\n", path); @@ -129,7 +130,6 @@ static void prevent_forking(void) if (ret != 1 && !my_args.quiet) fprintf(stderr, "Failed to write to \"%s\"\n", path); - close(fd); return; } } From a08bfbe3403079fe40da34117303aaebfe732eb0 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Thu, 26 Mar 2020 12:51:31 +0100 Subject: [PATCH 3/5] tree-wide: harden mount option parsing Signed-off-by: Christian Brauner --- src/include/strlcat.c | 12 +++--- src/include/strlcat.h | 2 +- src/lxc/conf.c | 68 ++++++++++++++++++--------------- src/lxc/confile.c | 2 +- src/lxc/criu.c | 4 +- src/lxc/storage/btrfs.c | 4 +- src/lxc/storage/dir.c | 4 +- src/lxc/storage/overlay.c | 7 ++-- src/lxc/storage/storage_utils.c | 5 +-- src/lxc/storage/zfs.c | 5 ++- src/lxc/string_utils.h | 15 ++++++++ 11 files changed, 76 insertions(+), 52 deletions(-) diff --git a/src/include/strlcat.c b/src/include/strlcat.c index 42fa3f32c5..ded647c6f2 100644 --- a/src/include/strlcat.c +++ b/src/include/strlcat.c @@ -27,11 +27,13 @@ #include "strlcpy.h" #endif -size_t strlcat(char *d, const char *s, size_t n) +size_t strlcat(char *src, const char *append, size_t len) { - size_t l = strnlen(d, n); - if (l == n) - return l + strlen(s); + size_t src_len; - return l + strlcpy(d + l, s, n - l); + src_len = strnlen(src, len); + if (src_len == len) + return src_len + strlen(append); + + return src_len + strlcpy(src + src_len, append, len - src_len); } diff --git a/src/include/strlcat.h b/src/include/strlcat.h index 1b51e00e66..60f7d8e053 100644 --- a/src/include/strlcat.h +++ b/src/include/strlcat.h @@ -24,6 +24,6 @@ #include -extern size_t strlcat(char *d, const char *s, size_t n); +extern size_t strlcat(char *src, const char *append, size_t len); #endif diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 0c36737c61..4bab3ee67a 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -1694,61 +1694,70 @@ static int lxc_setup_console(const struct lxc_rootfs *rootfs, return lxc_setup_ttydir_console(rootfs, console, ttydir); } -static void parse_mntopt(char *opt, unsigned long *flags, char **data, size_t size) +static int parse_mntopt(char *opt, unsigned long *flags, char **data, size_t size) { - struct mount_opt *mo; + ssize_t ret; /* If '=' is contained in opt, the option must go into data. */ if (!strchr(opt, '=')) { - - /* If opt is found in mount_opt, set or clear flags. - * Otherwise append it to data. */ + /* + * If opt is found in mount_opt, set or clear flags. + * Otherwise append it to data. + */ size_t opt_len = strlen(opt); - for (mo = &mount_opt[0]; mo->name != NULL; mo++) { + for (struct mount_opt *mo = &mount_opt[0]; mo->name != NULL; mo++) { size_t mo_name_len = strlen(mo->name); + if (opt_len == mo_name_len && strncmp(opt, mo->name, mo_name_len) == 0) { if (mo->clear) *flags &= ~mo->flag; else *flags |= mo->flag; - return; + return 0; } } } - if (strlen(*data)) - (void)strlcat(*data, ",", size); + if (strlen(*data)) { + ret = strlcat(*data, ",", size); + if (ret < 0) + return log_error_errno(ret, errno, "Failed to append \",\" to %s", *data); + } + + ret = strlcat(*data, opt, size); + if (ret < 0) + return log_error_errno(ret, errno, "Failed to append \"%s\" to %s", opt, *data); - (void)strlcat(*data, opt, size); + return 0; } int parse_mntopts(const char *mntopts, unsigned long *mntflags, char **mntdata) { - __do_free char *data = NULL, *s = NULL; - char *p; + __do_free char *mntopts_new = NULL, *mntopts_dup = NULL; + char *mntopt_cur = NULL; size_t size; - *mntdata = NULL; - *mntflags = 0L; + if (*mntdata || *mntflags) + return ret_errno(EINVAL); if (!mntopts) return 0; - s = strdup(mntopts); - if (!s) - return -1; + mntopts_dup = strdup(mntopts); + if (!mntopts_dup) + return ret_errno(ENOMEM); - size = strlen(s) + 1; - data = malloc(size); - if (!data) - return -1; - *data = 0; + size = strlen(mntopts_dup) + 1; + mntopts_new = zalloc(size); + if (!mntopts_new) + return ret_errno(ENOMEM); - lxc_iterate_parts(p, s, ",") - parse_mntopt(p, mntflags, &data, size); + lxc_iterate_parts(mntopt_cur, mntopts_dup, ",") + if (parse_mntopt(mntopt_cur, mntflags, &mntopts_new, size) < 0) + return ret_errno(EINVAL); - if (*data) - *mntdata = move_ptr(data); + if (*mntopts_new) + *mntdata = move_ptr(mntopts_new); return 0; } @@ -2001,11 +2010,10 @@ static inline int mount_entry_on_generic(struct mntent *mntent, const char *lxc_path) { __do_free char *mntdata = NULL; + unsigned long mntflags = 0, pflags = 0; + char *rootfs_path = NULL; int ret; - unsigned long mntflags; bool dev, optional, relative; - unsigned long pflags = 0; - char *rootfs_path = NULL; optional = hasmntopt(mntent, "optional") != NULL; dev = hasmntopt(mntent, "dev") != NULL; @@ -2030,7 +2038,7 @@ static inline int mount_entry_on_generic(struct mntent *mntent, ret = parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata); if (ret < 0) - return -1; + return ret; ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type, mntflags, pflags, mntdata, optional, dev, relative, rootfs_path); diff --git a/src/lxc/confile.c b/src/lxc/confile.c index a24bcff745..0ca577fa3f 100644 --- a/src/lxc/confile.c +++ b/src/lxc/confile.c @@ -2572,9 +2572,9 @@ static int set_config_rootfs_mount(const char *key, const char *value, static int set_config_rootfs_options(const char *key, const char *value, struct lxc_conf *lxc_conf, void *data) { - int ret; unsigned long mflags = 0, pflags = 0; char *mdata = NULL, *opts = NULL; + int ret; struct lxc_rootfs *rootfs = &lxc_conf->rootfs; ret = parse_mntopts(value, &mflags, &mdata); diff --git a/src/lxc/criu.c b/src/lxc/criu.c index 421da89416..1a909bb6c4 100644 --- a/src/lxc/criu.c +++ b/src/lxc/criu.c @@ -367,9 +367,9 @@ static void exec_criu(struct cgroup_ops *cgroup_ops, struct lxc_conf *conf, goto err; while (getmntent_r(mnts, &mntent, buf, sizeof(buf))) { - char *mntdata; + unsigned long flags = 0; + char *mntdata = NULL; char arg[2 * PATH_MAX + 2]; - unsigned long flags; if (parse_mntopts(mntent.mnt_opts, &flags, &mntdata) < 0) goto err; diff --git a/src/lxc/storage/btrfs.c b/src/lxc/storage/btrfs.c index 47f2dd3c4e..0929305197 100644 --- a/src/lxc/storage/btrfs.c +++ b/src/lxc/storage/btrfs.c @@ -192,8 +192,8 @@ bool btrfs_detect(const char *path) int btrfs_mount(struct lxc_storage *bdev) { - unsigned long mntflags; - char *mntdata; + unsigned long mntflags = 0; + char *mntdata = NULL; const char *src; int ret; diff --git a/src/lxc/storage/dir.c b/src/lxc/storage/dir.c index 9b3e673b3e..d09e570ec9 100644 --- a/src/lxc/storage/dir.c +++ b/src/lxc/storage/dir.c @@ -138,9 +138,9 @@ bool dir_detect(const char *path) int dir_mount(struct lxc_storage *bdev) { - int ret; + char *mntdata = NULL; unsigned long mflags = 0, mntflags = 0, pflags = 0; - char *mntdata; + int ret; const char *src; if (strcmp(bdev->type, "dir")) diff --git a/src/lxc/storage/overlay.c b/src/lxc/storage/overlay.c index a18b947fa1..770785cfdc 100644 --- a/src/lxc/storage/overlay.c +++ b/src/lxc/storage/overlay.c @@ -342,13 +342,12 @@ bool ovl_detect(const char *path) int ovl_mount(struct lxc_storage *bdev) { - __do_free char *options = NULL, - *options_work = NULL; + __do_free char *options = NULL, *options_work = NULL; + unsigned long mntflags = 0; + char *mntdata = NULL; char *tmp, *dup, *lower, *upper; char *work, *lastslash; size_t len, len2; - unsigned long mntflags; - char *mntdata; int ret, ret2; if (strcmp(bdev->type, "overlay") && strcmp(bdev->type, "overlayfs")) diff --git a/src/lxc/storage/storage_utils.c b/src/lxc/storage/storage_utils.c index 79ee62ecbd..a3ee353e5e 100644 --- a/src/lxc/storage/storage_utils.c +++ b/src/lxc/storage/storage_utils.c @@ -315,9 +315,8 @@ int find_fstype_cb(char *buffer, void *data) const char *target; const char *options; } *cbarg = data; - - unsigned long mntflags; - char *mntdata; + unsigned long mntflags = 0; + char *mntdata = NULL; char *fstype; /* we don't try 'nodev' entries */ diff --git a/src/lxc/storage/zfs.c b/src/lxc/storage/zfs.c index d745f2e392..4cc171fd80 100644 --- a/src/lxc/storage/zfs.c +++ b/src/lxc/storage/zfs.c @@ -159,11 +159,12 @@ bool zfs_detect(const char *path) int zfs_mount(struct lxc_storage *bdev) { + unsigned long mntflags = 0; + char *mntdata = NULL; int ret; size_t oldlen, newlen, totallen; - char *mntdata, *tmp; + char *tmp; const char *src; - unsigned long mntflags; char cmd_output[PATH_MAX] = {0}; if (strcmp(bdev->type, "zfs")) diff --git a/src/lxc/string_utils.h b/src/lxc/string_utils.h index 2720f1097e..0f7d2ff21e 100644 --- a/src/lxc/string_utils.h +++ b/src/lxc/string_utils.h @@ -10,6 +10,10 @@ #include "initutils.h" #include "macro.h" +#ifndef HAVE_STRLCAT +#include "include/strlcat.h" +#endif + /* convert variadic argument lists to arrays (for execl type argument lists) */ extern char **lxc_va_arg_list_to_argv(va_list ap, size_t skip, int do_strdup); extern const char **lxc_va_arg_list_to_argv_const(va_list ap, size_t skip); @@ -103,4 +107,15 @@ static inline bool is_empty_string(const char *s) return !s || strcmp(s, "") == 0; } +static inline ssize_t safe_strlcat(char *src, const char *append, size_t len) +{ + size_t new_len; + + new_len = strlcat(src, append, len); + if (new_len >= len) + return ret_errno(EINVAL); + + return (ssize_t)new_len; +} + #endif /* __LXC_STRING_UTILS_H */ From 0f2e356612f454d4d0e2150b866f81829ba73dd4 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Thu, 26 Mar 2020 15:32:29 +0100 Subject: [PATCH 4/5] dir: use cleanup macro in dir_mount() Signed-off-by: Christian Brauner --- src/lxc/storage/dir.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/lxc/storage/dir.c b/src/lxc/storage/dir.c index d09e570ec9..b657cc0091 100644 --- a/src/lxc/storage/dir.c +++ b/src/lxc/storage/dir.c @@ -138,7 +138,7 @@ bool dir_detect(const char *path) int dir_mount(struct lxc_storage *bdev) { - char *mntdata = NULL; + __do_free char *mntdata = NULL; unsigned long mflags = 0, mntflags = 0, pflags = 0; int ret; const char *src; @@ -152,14 +152,12 @@ int dir_mount(struct lxc_storage *bdev) ret = parse_mntopts(bdev->mntopts, &mntflags, &mntdata); if (ret < 0) { ERROR("Failed to parse mount options \"%s\"", bdev->mntopts); - free(mntdata); return -EINVAL; } ret = parse_propagationopts(bdev->mntopts, &pflags); if (ret < 0) { ERROR("Failed to parse propagation options \"%s\"", bdev->mntopts); - free(mntdata); return -EINVAL; } @@ -175,12 +173,10 @@ int dir_mount(struct lxc_storage *bdev) if (ret < 0) { SYSERROR("Failed to mount \"%s\" on \"%s\"", src, bdev->dest); - free(mntdata); return -1; } TRACE("Mounted \"%s\" on \"%s\"", src, bdev->dest); - free(mntdata); return ret; } From 65146c9729e618c22f4752a5eecae1b806500600 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Thu, 26 Mar 2020 15:47:11 +0100 Subject: [PATCH 5/5] dir: improve dir backend Signed-off-by: Christian Brauner --- src/lxc/storage/dir.c | 125 +++++++++++++++++++----------------------- 1 file changed, 56 insertions(+), 69 deletions(-) diff --git a/src/lxc/storage/dir.c b/src/lxc/storage/dir.c index b657cc0091..18a10a42f9 100644 --- a/src/lxc/storage/dir.c +++ b/src/lxc/storage/dir.c @@ -4,16 +4,20 @@ #define _GNU_SOURCE 1 #endif #include +#include #include #include "config.h" #include "log.h" +#include "macro.h" +#include "memory_utils.h" #include "storage.h" #include "utils.h" lxc_log_define(dir, lxc); -/* For a simple directory bind mount, we substitute the old container name and +/* + * For a simple directory bind mount, we substitute the old container name and * paths for the new. */ int dir_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, @@ -25,33 +29,26 @@ int dir_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, int ret; size_t len; - if (snap) { - ERROR("Directories cannot be snapshotted"); - return -1; - } + if (snap) + return log_error_errno(-EINVAL, EINVAL, "Directories cannot be snapshotted"); if (!orig->dest || !orig->src) - return -1; + return ret_errno(EINVAL); - len = strlen(lxcpath) + strlen(cname) + strlen("rootfs") + 4 + 3; + len = STRLITERALLEN("dir:") + strlen(lxcpath) + STRLITERALLEN("/") + + strlen(cname) + STRLITERALLEN("/rootfs") + 1; new->src = malloc(len); - if (!new->src) { - ERROR("Failed to allocate memory"); - return -1; - } + if (!new->src) + return ret_errno(ENOMEM); ret = snprintf(new->src, len, "dir:%s/%s/rootfs", lxcpath, cname); - if (ret < 0 || (size_t)ret >= len) { - ERROR("Failed to create string"); - return -1; - } + if (ret < 0 || (size_t)ret >= len) + return ret_errno(EIO); src_no_prefix = lxc_storage_get_path(new->src, new->type); new->dest = strdup(src_no_prefix); - if (!new->dest) { - ERROR("Failed to duplicate string \"%s\"", new->src); - return -1; - } + if (!new->dest) + return log_error_errno(-ENOMEM, ENOMEM, "Failed to duplicate string \"%s\"", new->src); TRACE("Created new path \"%s\" for dir storage driver", new->dest); return 0; @@ -60,42 +57,37 @@ int dir_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, int dir_create(struct lxc_storage *bdev, const char *dest, const char *n, struct bdev_specs *specs, const struct lxc_conf *conf) { + __do_free char *bdev_src = NULL, *bdev_dest = NULL; int ret; const char *src; size_t len; - /* strlen("dir:") */ - len = 4; + len = STRLITERALLEN("dir:"); if (specs && specs->dir) src = specs->dir; else src = dest; len += strlen(src) + 1; - bdev->src = malloc(len); - if (!bdev->src) { - ERROR("Failed to allocate memory"); - return -1; - } + bdev_src = malloc(len); + if (!bdev_src) + return ret_errno(ENOMEM); - ret = snprintf(bdev->src, len, "dir:%s", src); - if (ret < 0 || (size_t)ret >= len) { - ERROR("Failed to create string"); - return -1; - } + ret = snprintf(bdev_src, len, "dir:%s", src); + if (ret < 0 || (size_t)ret >= len) + return ret_errno(EIO); - bdev->dest = strdup(dest); - if (!bdev->dest) { - ERROR("Failed to duplicate string \"%s\"", dest); - return -1; - } + bdev_dest = strdup(dest); + if (!bdev_dest) + return ret_errno(ENOMEM); ret = mkdir_p(dest, 0755); - if (ret < 0) { - ERROR("Failed to create directory \"%s\"", dest); - return -1; - } + if (ret < 0) + return log_error_errno(-errno, errno, "Failed to create directory \"%s\"", dest); + TRACE("Created directory \"%s\"", dest); + bdev->src = move_ptr(bdev_src); + bdev->dest = move_ptr(bdev_dest); return 0; } @@ -108,10 +100,8 @@ int dir_destroy(struct lxc_storage *orig) src = lxc_storage_get_path(orig->src, orig->src); ret = lxc_rmdir_onedev(src, NULL); - if (ret < 0) { - ERROR("Failed to delete \"%s\"", src); - return -1; - } + if (ret < 0) + return log_error_errno(ret, errno, "Failed to delete \"%s\"", src); return 0; } @@ -125,10 +115,8 @@ bool dir_detect(const char *path) return true; ret = stat(path, &statbuf); - if (ret == -1 && errno == EPERM) { - SYSERROR("dir_detect: failed to look at \"%s\"", path); - return false; - } + if (ret == -1 && errno == EPERM) + return log_error_errno(false, errno, "dir_detect: failed to look at \"%s\"", path); if (ret == 0 && S_ISDIR(statbuf.st_mode)) return true; @@ -150,43 +138,42 @@ int dir_mount(struct lxc_storage *bdev) return -22; ret = parse_mntopts(bdev->mntopts, &mntflags, &mntdata); - if (ret < 0) { - ERROR("Failed to parse mount options \"%s\"", bdev->mntopts); - return -EINVAL; - } + if (ret < 0) + return log_error_errno(ret, errno, "Failed to parse mount options \"%s\"", bdev->mntopts); ret = parse_propagationopts(bdev->mntopts, &pflags); - if (ret < 0) { - ERROR("Failed to parse propagation options \"%s\"", bdev->mntopts); - return -EINVAL; - } + if (ret < 0) + return log_error_errno(-EINVAL, EINVAL, "Failed to parse mount propagation options \"%s\"", bdev->mntopts); src = lxc_storage_get_path(bdev->src, bdev->type); ret = mount(src, bdev->dest, "bind", MS_BIND | MS_REC | mntflags | pflags, mntdata); - if ((0 == ret) && (mntflags & MS_RDONLY)) { - DEBUG("Remounting \"%s\" on \"%s\" readonly", - src ? src : "(none)", bdev->dest ? bdev->dest : "(none)"); + if (ret < 0) + return log_error_errno(-errno, errno, "Failed to mount \"%s\" on \"%s\"", src, bdev->dest); + + if (ret == 0 && (mntflags & MS_RDONLY)) { mflags = add_required_remount_flags(src, bdev->dest, MS_BIND | MS_REC | mntflags | pflags | MS_REMOUNT); ret = mount(src, bdev->dest, "bind", mflags, mntdata); + if (ret < 0) + return log_error_errno(-errno, errno, "Failed to remount \"%s\" on \"%s\" read-only with options \"%s\", mount flags \"%lu\", and propagation flags \"%lu\"", + src ? src : "(none)", bdev->dest ? bdev->dest : "(none)", mntdata, mflags, pflags); + else + DEBUG("Remounted \"%s\" on \"%s\" read-only with options \"%s\", mount flags \"%lu\", and propagation flags \"%lu\"", + src ? src : "(none)", bdev->dest ? bdev->dest : "(none)", mntdata, mflags, pflags); } - if (ret < 0) { - SYSERROR("Failed to mount \"%s\" on \"%s\"", src, bdev->dest); - return -1; - } - - TRACE("Mounted \"%s\" on \"%s\"", src, bdev->dest); - return ret; + TRACE("Mounted \"%s\" on \"%s\" with options \"%s\", mount flags \"%lu\", and propagation flags \"%lu\"", + src ? src : "(none)", bdev->dest ? bdev->dest : "(none)", mntdata, mflags, pflags); + return 0; } int dir_umount(struct lxc_storage *bdev) { if (strcmp(bdev->type, "dir")) - return -22; + return ret_errno(EINVAL); if (!bdev->src || !bdev->dest) - return -22; + return ret_errno(EINVAL); - return umount(bdev->dest); + return umount2(bdev->dest, MNT_DETACH); }