From 777827cb3a76ecab24131543c8a24f9b85f5cefd Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Tue, 3 Aug 2021 09:22:46 +0200 Subject: [PATCH 1/5] conf: log failure to create tty mountpoint Signed-off-by: Christian Brauner --- src/lxc/conf.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 8dcfc60f3..37104761e 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -946,11 +946,20 @@ static int open_ttymnt_at(int dfd, const char *path) { int fd; - fd = open_at(dfd, path, PROTECT_OPEN | O_CREAT | O_EXCL, - PROTECT_LOOKUP_BENEATH, 0); - if (fd < 0 && (errno == ENXIO || errno == EEXIST)) - fd = open_at(dfd, path, PROTECT_OPATH_FILE, - PROTECT_LOOKUP_BENEATH, 0); + fd = open_at(dfd, path, + PROTECT_OPEN | O_CREAT | O_EXCL, + PROTECT_LOOKUP_BENEATH, + 0); + if (fd < 0) { + if (!IN_SET(errno, ENXIO, EEXIST)) + return syserror("Failed to create \"%d/\%s\"", dfd, path); + + SYSINFO("Failed to create \"%d/\%s\"", dfd, path); + fd = open_at(dfd, path, + PROTECT_OPATH_FILE, + PROTECT_LOOKUP_BENEATH, + 0); + } return fd; } From 0f43436cbefa3466986e2262d5ce6a270b1fd801 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Tue, 3 Aug 2021 12:13:01 +0200 Subject: [PATCH 2/5] conf: let parse_vfs_attr() handle legacy mount flags as well Signed-off-by: Christian Brauner --- src/lxc/conf.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 37104761e..969ae7609 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -2185,12 +2185,14 @@ static int parse_vfs_attr(struct lxc_mount_options *opts, char *opt, size_t size if (strequal(mo->name, "rbind")) { opts->recursive = 1; opts->bind = 1; + opts->mnt_flags |= mo->legacy_flag; /* MS_BIND | MS_REC */ return 0; } /* This is a bind-mount. */ if (strequal(mo->name, "bind")) { opts->bind = 1; + opts->mnt_flags |= mo->legacy_flag; /* MS_BIND */ return 0; } @@ -2199,21 +2201,24 @@ static int parse_vfs_attr(struct lxc_mount_options *opts, char *opt, size_t size if (mo->clear) { opts->attr.attr_clr |= mo->flag; + opts->mnt_flags &= ~mo->legacy_flag; TRACE("Lowering %s", mo->name); } else { opts->attr.attr_set |= mo->flag; + opts->mnt_flags |= mo->legacy_flag; TRACE("Raising %s", mo->name); } return 0; } - for (struct mount_opt *mo = &mount_opt[0]; mo->name != NULL; mo++) { + for (struct mount_opt *mo = &propagation_opt[0]; mo->name != NULL; mo++) { if (!strnequal(opt, mo->name, strlen(mo->name))) continue; /* TODO: Handle recursive propagation requests. */ opts->attr.propagation = mo->flag; + opts->mnt_flags |= mo->legacy_flag; return 0; } From 8cf6a646757b3e0b48fca0f6f736c1b3f9c7a7b4 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Tue, 3 Aug 2021 12:51:24 +0200 Subject: [PATCH 3/5] mount_utils: make some mount helpers static inline Signed-off-by: Christian Brauner --- src/lxc/mount_utils.c | 31 ++++--------------------------- src/lxc/mount_utils.h | 39 ++++++++++++++++++++++++++++----------- 2 files changed, 32 insertions(+), 38 deletions(-) diff --git a/src/lxc/mount_utils.c b/src/lxc/mount_utils.c index 783503aae..b04c2646d 100644 --- a/src/lxc/mount_utils.c +++ b/src/lxc/mount_utils.c @@ -307,11 +307,10 @@ int move_detached_mount(int dfd_from, int dfd_to, const char *path_to, return 0; } -static int __fd_bind_mount(int dfd_from, const char *path_from, - __u64 o_flags_from, __u64 resolve_flags_from, - int dfd_to, const char *path_to, __u64 o_flags_to, - __u64 resolve_flags_to, unsigned int attr_flags, - int userns_fd, bool recursive) +int __fd_bind_mount(int dfd_from, const char *path_from, __u64 o_flags_from, + __u64 resolve_flags_from, int dfd_to, const char *path_to, + __u64 o_flags_to, __u64 resolve_flags_to, __u64 attr_flags, + int userns_fd, bool recursive) { struct lxc_mount_attr attr = { .attr_set = attr_flags, @@ -360,28 +359,6 @@ static int __fd_bind_mount(int dfd_from, const char *path_from, resolve_flags_to); } -int fd_mount_idmapped(int dfd_from, const char *path_from, - __u64 o_flags_from, __u64 resolve_flags_from, - int dfd_to, const char *path_to, - __u64 o_flags_to, __u64 resolve_flags_to, - unsigned int attr_flags, int userns_fd, bool recursive) -{ - return __fd_bind_mount(dfd_from, path_from, o_flags_from, resolve_flags_from, - dfd_to, path_to, o_flags_to, resolve_flags_to, - attr_flags, userns_fd, recursive); -} - -int fd_bind_mount(int dfd_from, const char *path_from, - __u64 o_flags_from, __u64 resolve_flags_from, - int dfd_to, const char *path_to, - __u64 o_flags_to, __u64 resolve_flags_to, - unsigned int attr_flags, bool recursive) -{ - return __fd_bind_mount(dfd_from, path_from, o_flags_from, resolve_flags_from, - dfd_to, path_to, o_flags_to, resolve_flags_to, - attr_flags, -EBADF, recursive); -} - int calc_remount_flags_new(int dfd_from, const char *path_from, __u64 o_flags_from, __u64 resolve_flags_from, bool remount, unsigned long cur_flags, diff --git a/src/lxc/mount_utils.h b/src/lxc/mount_utils.h index 6fed1a0a9..d24949714 100644 --- a/src/lxc/mount_utils.h +++ b/src/lxc/mount_utils.h @@ -186,17 +186,34 @@ static inline int fs_mount(const char *fs_name, int dfd_from, return fs_attach(fd_fs, dfd_to, path_to, o_flags_to, resolve_flags_to, attr_flags); } -__hidden extern int fd_bind_mount(int dfd_from, const char *path_from, - __u64 o_flags_from, __u64 resolve_flags_from, - int dfd_to, const char *path_to, - __u64 o_flags_to, __u64 resolve_flags_to, - unsigned int attr_flags, bool recursive); -__hidden extern int fd_mount_idmapped(int dfd_from, const char *path_from, - __u64 o_flags_from, __u64 resolve_flags_from, - int dfd_to, const char *path_to, - __u64 o_flags_to, __u64 resolve_flags_to, - unsigned int attr_flags, int userns_fd, - bool recursive); +__hidden extern int __fd_bind_mount(int dfd_from, const char *path_from, + __u64 o_flags_from, + __u64 resolve_flags_from, int dfd_to, + const char *path_to, __u64 o_flags_to, + __u64 resolve_flags_to, __u64 attr_flags, + int userns_fd, bool recursive); +static inline int fd_mount_idmapped(int dfd_from, const char *path_from, + __u64 o_flags_from, + __u64 resolve_flags_from, int dfd_to, + const char *path_to, __u64 o_flags_to, + __u64 resolve_flags_to, __u64 attr_flags, + int userns_fd, bool recursive) +{ + return __fd_bind_mount(dfd_from, path_from, o_flags_from, resolve_flags_from, + dfd_to, path_to, o_flags_to, resolve_flags_to, + attr_flags, userns_fd, recursive); +} + +static inline int fd_bind_mount(int dfd_from, const char *path_from, + __u64 o_flags_from, __u64 resolve_flags_from, + int dfd_to, const char *path_to, + __u64 o_flags_to, __u64 resolve_flags_to, + __u64 attr_flags, bool recursive) +{ + return __fd_bind_mount(dfd_from, path_from, o_flags_from, resolve_flags_from, + dfd_to, path_to, o_flags_to, resolve_flags_to, + attr_flags, -EBADF, recursive); +} __hidden extern int create_detached_idmapped_mount(const char *path, int userns_fd, bool recursive); __hidden extern int move_detached_mount(int dfd_from, int dfd_to, From 704cadd524b8c50321210ee66e7ab3e02ab4852f Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Tue, 3 Aug 2021 13:16:45 +0200 Subject: [PATCH 4/5] conf: allow mount options for rootfs when using new mount api Signed-off-by: Christian Brauner --- src/lxc/conf.c | 27 +++++++++++++++++++++------ src/lxc/conf.h | 1 + src/lxc/confile.c | 26 ++++++++++---------------- src/lxc/mount_utils.c | 38 +++++++++++++++++++++++++++++++++----- src/lxc/mount_utils.h | 21 +++++++++++++-------- src/lxc/storage/dir.c | 11 ++++++++--- 6 files changed, 86 insertions(+), 38 deletions(-) diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 969ae7609..10b6010d9 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -615,6 +615,7 @@ int lxc_rootfs_prepare_parent(struct lxc_handler *handler) __do_close int dfd_idmapped = -EBADF, fd_userns = -EBADF; struct lxc_rootfs *rootfs = &handler->conf->rootfs; struct lxc_storage *storage = rootfs->storage; + const struct lxc_mount_options *mnt_opts = &rootfs->mnt_opts; int ret; const char *path_source; @@ -643,7 +644,9 @@ int lxc_rootfs_prepare_parent(struct lxc_handler *handler) path_source = lxc_storage_get_path(storage->src, storage->type); - dfd_idmapped = create_detached_idmapped_mount(path_source, fd_userns, true); + dfd_idmapped = create_detached_idmapped_mount(path_source, fd_userns, true, + mnt_opts->attr.attr_set, + mnt_opts->attr.attr_clr); if (dfd_idmapped < 0) return syserror("Failed to create detached idmapped mount"); @@ -1008,7 +1011,10 @@ static int lxc_setup_ttys(struct lxc_conf *conf) PROTECT_LOOKUP_BENEATH_XDEV, fd_to, "", PROTECT_OPATH_FILE, - PROTECT_LOOKUP_BENEATH_XDEV, 0, + PROTECT_LOOKUP_BENEATH_XDEV, + 0, + 0, + 0, false); else ret = mount_fd(tty->pty, fd_to, "none", MS_BIND, 0); @@ -1042,7 +1048,10 @@ static int lxc_setup_ttys(struct lxc_conf *conf) PROTECT_LOOKUP_BENEATH_XDEV, fd_to, "", PROTECT_OPATH_FILE, - PROTECT_LOOKUP_BENEATH, 0, + PROTECT_LOOKUP_BENEATH, + 0, + 0, + 0, false); else ret = mount_fd(tty->pty, fd_to, "none", MS_BIND, 0); @@ -1360,7 +1369,11 @@ static int lxc_fill_autodev(struct lxc_rootfs *rootfs) PROTECT_LOOKUP_BENEATH_XDEV, rootfs->dfd_dev, device->name, PROTECT_OPATH_FILE, - PROTECT_LOOKUP_BENEATH, 0, false); + PROTECT_LOOKUP_BENEATH, + 0, + 0, + 0, + false); } else { char path[PATH_MAX]; @@ -1874,7 +1887,7 @@ static int bind_mount_console(int fd_devpts, struct lxc_rootfs *rootfs, * we're operating directly on the fd. */ if (can_use_mount_api()) - return fd_bind_mount(fd_pty, "", 0, 0, fd_to, "", 0, 0, 0, false); + return fd_bind_mount(fd_pty, "", 0, 0, fd_to, "", 0, 0, 0, 0, 0, false); return mount_fd(fd_pty, fd_to, "none", MS_BIND, 0); } @@ -2015,6 +2028,8 @@ static int lxc_setup_ttydir_console(int fd_devpts, struct lxc_rootfs *rootfs, PROTECT_OPATH_FILE, PROTECT_LOOKUP_BENEATH, 0, + 0, + 0, false); else ret = mount_fd(fd_dev_console, fd_reg_console, "none", MS_BIND, 0); @@ -2225,7 +2240,7 @@ static int parse_vfs_attr(struct lxc_mount_options *opts, char *opt, size_t size return 0; } -static int parse_mount_attrs(struct lxc_mount_options *opts, const char *mntopts) +int parse_mount_attrs(struct lxc_mount_options *opts, const char *mntopts) { __do_free char *mntopts_new = NULL, *mntopts_dup = NULL; char *end = NULL, *mntopt_cur = NULL; diff --git a/src/lxc/conf.h b/src/lxc/conf.h index cdefc2ad5..c5bf3a702 100644 --- a/src/lxc/conf.h +++ b/src/lxc/conf.h @@ -546,6 +546,7 @@ __hidden extern int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *), v __hidden extern int parse_mntopts_legacy(const char *mntopts, unsigned long *mntflags, char **mntdata); __hidden extern int parse_propagationopts(const char *mntopts, unsigned long *pflags); __hidden extern int parse_lxc_mount_attrs(struct lxc_mount_options *opts, char *mnt_opts); +__hidden extern int parse_mount_attrs(struct lxc_mount_options *opts, const char *mntopts); __hidden extern void tmp_proc_unmount(struct lxc_conf *lxc_conf); __hidden extern void suggest_default_idmap(void); __hidden extern FILE *make_anonymous_mount_file(struct lxc_list *mount, bool include_nesting_helpers); diff --git a/src/lxc/confile.c b/src/lxc/confile.c index ca2bb0d37..0e327d666 100644 --- a/src/lxc/confile.c +++ b/src/lxc/confile.c @@ -2786,7 +2786,7 @@ 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) { - __do_free char *__data = NULL, *dup = NULL, *mdata = NULL, *opts = NULL; + __do_free char *dup = NULL, *raw_options = NULL; struct lxc_rootfs *rootfs = &lxc_conf->rootfs; struct lxc_mount_options *mnt_opts = &rootfs->mnt_opts; int ret; @@ -2795,6 +2795,10 @@ static int set_config_rootfs_options(const char *key, const char *value, if (lxc_config_value_empty(value)) return 0; + ret = set_config_string_item(&raw_options, value); + if (ret < 0) + return ret_errno(ENOMEM); + dup = strdup(value); if (!dup) return -ENOMEM; @@ -2802,27 +2806,17 @@ static int set_config_rootfs_options(const char *key, const char *value, ret = parse_lxc_mount_attrs(mnt_opts, dup); if (ret < 0) return ret; - __data = mnt_opts->data; - - ret = parse_mntopts_legacy(dup, &mnt_opts->mnt_flags, &mdata); - if (ret < 0) - return ret_errno(EINVAL); - - ret = parse_propagationopts(dup, &mnt_opts->prop_flags); - if (ret < 0) - return ret_errno(EINVAL); - - ret = set_config_string_item(&opts, dup); - if (ret < 0) - return ret_errno(ENOMEM); + /* Make sure we're only valid LXC specific mount options. */ if (mnt_opts->create_dir || mnt_opts->create_file || mnt_opts->optional || mnt_opts->relative) return syserror_set(-EINVAL, "Invalid LXC specific mount option for rootfs mount"); - mnt_opts->data = move_ptr(mdata); - rootfs->options = move_ptr(opts); + ret = parse_mount_attrs(mnt_opts, dup); + if (ret < 0) + return ret_errno(EINVAL); + rootfs->options = move_ptr(raw_options); return 0; } diff --git a/src/lxc/mount_utils.c b/src/lxc/mount_utils.c index b04c2646d..945de8c1a 100644 --- a/src/lxc/mount_utils.c +++ b/src/lxc/mount_utils.c @@ -26,6 +26,25 @@ lxc_log_define(mount_utils, lxc); +/* + * Since the MOUNT_ATTR_ values are an enum, not a bitmap, users wanting + * to transition to a different atime setting cannot simply specify the atime + * setting in @attr_set, but must also specify MOUNT_ATTR__ATIME in the + * @attr_clr field. + */ +static inline void set_atime(struct lxc_mount_attr *attr) +{ + switch (attr->attr_set & MOUNT_ATTR__ATIME) { + case MOUNT_ATTR_RELATIME: + __fallthrough; + case MOUNT_ATTR_NOATIME: + __fallthrough; + case MOUNT_ATTR_STRICTATIME: + attr->attr_clr = MOUNT_ATTR__ATIME; + break; + } +} + int mnt_attributes_new(unsigned int old_flags, unsigned int *new_flags) { unsigned int flags = 0; @@ -249,18 +268,22 @@ int fs_attach(int fd_fs, return 0; } -int create_detached_idmapped_mount(const char *path, int userns_fd, bool recursive) +int create_detached_idmapped_mount(const char *path, int userns_fd, + bool recursive, __u64 attr_set, __u64 attr_clr) { __do_close int fd_tree_from = -EBADF; unsigned int open_tree_flags = OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC; struct lxc_mount_attr attr = { - .attr_set = MOUNT_ATTR_IDMAP, + .attr_set = MOUNT_ATTR_IDMAP | attr_set, + .attr_clr = attr_clr, .userns_fd = userns_fd, .propagation = MS_SLAVE, }; int ret; + set_atime(&attr); + TRACE("Idmapped mount \"%s\" requested with user namespace fd %d", path, userns_fd); if (recursive) @@ -309,17 +332,22 @@ int move_detached_mount(int dfd_from, int dfd_to, const char *path_to, int __fd_bind_mount(int dfd_from, const char *path_from, __u64 o_flags_from, __u64 resolve_flags_from, int dfd_to, const char *path_to, - __u64 o_flags_to, __u64 resolve_flags_to, __u64 attr_flags, - int userns_fd, bool recursive) + __u64 o_flags_to, __u64 resolve_flags_to, __u64 attr_set, + __u64 attr_clr, __u64 propagation, int userns_fd, + bool recursive) { struct lxc_mount_attr attr = { - .attr_set = attr_flags, + .attr_set = attr_set, + .attr_clr = attr_clr, + .propagation = propagation, }; __do_close int __fd_from = -EBADF; __do_close int fd_tree_from = -EBADF; unsigned int open_tree_flags = AT_EMPTY_PATH | OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC; int fd_from, ret; + set_atime(&attr); + if (!is_empty_string(path_from)) { struct lxc_open_how how = { .flags = o_flags_from, diff --git a/src/lxc/mount_utils.h b/src/lxc/mount_utils.h index d24949714..7d6857866 100644 --- a/src/lxc/mount_utils.h +++ b/src/lxc/mount_utils.h @@ -190,32 +190,37 @@ __hidden extern int __fd_bind_mount(int dfd_from, const char *path_from, __u64 o_flags_from, __u64 resolve_flags_from, int dfd_to, const char *path_to, __u64 o_flags_to, - __u64 resolve_flags_to, __u64 attr_flags, + __u64 resolve_flags_to, __u64 attr_set, + __u64 attr_clr, __u64 propagation, int userns_fd, bool recursive); static inline int fd_mount_idmapped(int dfd_from, const char *path_from, __u64 o_flags_from, __u64 resolve_flags_from, int dfd_to, const char *path_to, __u64 o_flags_to, - __u64 resolve_flags_to, __u64 attr_flags, + __u64 resolve_flags_to, __u64 attr_set, + __u64 attr_clr, __u64 propagation, int userns_fd, bool recursive) { - return __fd_bind_mount(dfd_from, path_from, o_flags_from, resolve_flags_from, - dfd_to, path_to, o_flags_to, resolve_flags_to, - attr_flags, userns_fd, recursive); + return __fd_bind_mount(dfd_from, path_from, o_flags_from, + resolve_flags_from, dfd_to, path_to, o_flags_to, + resolve_flags_to, attr_set, attr_clr, + propagation, userns_fd, recursive); } static inline int fd_bind_mount(int dfd_from, const char *path_from, __u64 o_flags_from, __u64 resolve_flags_from, int dfd_to, const char *path_to, __u64 o_flags_to, __u64 resolve_flags_to, - __u64 attr_flags, bool recursive) + __u64 attr_set, __u64 attr_clr, + __u64 propagation, bool recursive) { return __fd_bind_mount(dfd_from, path_from, o_flags_from, resolve_flags_from, dfd_to, path_to, o_flags_to, resolve_flags_to, - attr_flags, -EBADF, recursive); + attr_set, attr_clr, propagation, -EBADF, recursive); } __hidden extern int create_detached_idmapped_mount(const char *path, - int userns_fd, bool recursive); + int userns_fd, bool recursive, + __u64 attr_set, __u64 attr_clr); __hidden extern int move_detached_mount(int dfd_from, int dfd_to, const char *path_to, __u64 o_flags_to, __u64 resolve_flags_to); diff --git a/src/lxc/storage/dir.c b/src/lxc/storage/dir.c index ab21d11ec..03ad036d5 100644 --- a/src/lxc/storage/dir.c +++ b/src/lxc/storage/dir.c @@ -165,9 +165,14 @@ int dir_mount(struct lxc_storage *bdev) ret = fd_bind_mount(fd_source, "", PROTECT_OPATH_DIRECTORY, - PROTECT_LOOKUP_BENEATH, fd_target, - "", PROTECT_OPATH_DIRECTORY, - PROTECT_LOOKUP_BENEATH, 0, true); + PROTECT_LOOKUP_BENEATH, + fd_target, "", + PROTECT_OPATH_DIRECTORY, + PROTECT_LOOKUP_BENEATH, + mnt_opts->attr.attr_set, + mnt_opts->attr.attr_clr, + mnt_opts->attr.propagation, + true); } } else { ret = mount(source, target, "bind", MS_BIND | MS_REC | mnt_opts->mnt_flags | mnt_opts->prop_flags, mnt_opts->data); From 587b2dff94657fb6afee0306bbe47fa61df85750 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Tue, 3 Aug 2021 14:40:28 +0200 Subject: [PATCH 5/5] tests: add test for rootfs mount options Signed-off-by: Christian Brauner --- .gitignore | 1 + src/tests/Makefile.am | 56 +++++++++++++ src/tests/rootfs_options.c | 161 +++++++++++++++++++++++++++++++++++++ 3 files changed, 218 insertions(+) create mode 100644 src/tests/rootfs_options.c diff --git a/.gitignore b/.gitignore index 0ec731bb7..ac6c1e909 100644 --- a/.gitignore +++ b/.gitignore @@ -107,6 +107,7 @@ src/tests/lxc-test-basic src/tests/lxc-test-cve-2019-5736 src/tests/lxc-test-mount-injection src/tests/lxc-test-sys-mixed +src/tests/lxc-test-rootfs-options config/compile config/config.guess diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am index 95cce8504..f22394a2d 100644 --- a/src/tests/Makefile.am +++ b/src/tests/Makefile.am @@ -759,6 +759,60 @@ if !HAVE_STRCHRNUL lxc_test_sys_mixed_SOURCES += ../include/strchrnul.c ../include/strchrnul.h endif +lxc_test_rootfs_options_SOURCES = rootfs_options.c \ + ../lxc/af_unix.c ../lxc/af_unix.h \ + ../lxc/caps.c ../lxc/caps.h \ + ../lxc/cgroups/cgfsng.c \ + ../lxc/cgroups/cgroup.c ../lxc/cgroups/cgroup.h \ + ../lxc/cgroups/cgroup2_devices.c ../lxc/cgroups/cgroup2_devices.h \ + ../lxc/cgroups/cgroup_utils.c ../lxc/cgroups/cgroup_utils.h \ + ../lxc/commands.c ../lxc/commands.h \ + ../lxc/commands_utils.c ../lxc/commands_utils.h \ + ../lxc/conf.c ../lxc/conf.h \ + ../lxc/confile.c ../lxc/confile.h \ + ../lxc/confile_utils.c ../lxc/confile_utils.h \ + ../lxc/error.c ../lxc/error.h \ + ../lxc/file_utils.c ../lxc/file_utils.h \ + ../include/netns_ifaddrs.c ../include/netns_ifaddrs.h \ + ../lxc/initutils.c ../lxc/initutils.h \ + ../lxc/log.c ../lxc/log.h \ + ../lxc/lxclock.c ../lxc/lxclock.h \ + ../lxc/mainloop.c ../lxc/mainloop.h \ + ../lxc/monitor.c ../lxc/monitor.h \ + ../lxc/mount_utils.c ../lxc/mount_utils.h \ + ../lxc/namespace.c ../lxc/namespace.h \ + ../lxc/network.c ../lxc/network.h \ + ../lxc/nl.c ../lxc/nl.h \ + ../lxc/parse.c ../lxc/parse.h \ + ../lxc/process_utils.c ../lxc/process_utils.h \ + ../lxc/ringbuf.c ../lxc/ringbuf.h \ + ../lxc/start.c ../lxc/start.h \ + ../lxc/state.c ../lxc/state.h \ + ../lxc/storage/btrfs.c ../lxc/storage/btrfs.h \ + ../lxc/storage/dir.c ../lxc/storage/dir.h \ + ../lxc/storage/loop.c ../lxc/storage/loop.h \ + ../lxc/storage/lvm.c ../lxc/storage/lvm.h \ + ../lxc/storage/nbd.c ../lxc/storage/nbd.h \ + ../lxc/storage/overlay.c ../lxc/storage/overlay.h \ + ../lxc/storage/rbd.c ../lxc/storage/rbd.h \ + ../lxc/storage/rsync.c ../lxc/storage/rsync.h \ + ../lxc/storage/storage.c ../lxc/storage/storage.h \ + ../lxc/storage/storage_utils.c ../lxc/storage/storage_utils.h \ + ../lxc/storage/zfs.c ../lxc/storage/zfs.h \ + ../lxc/sync.c ../lxc/sync.h \ + ../lxc/string_utils.c ../lxc/string_utils.h \ + ../lxc/terminal.c ../lxc/terminal.h \ + ../lxc/utils.c ../lxc/utils.h \ + ../lxc/uuid.c ../lxc/uuid.h \ + $(LSM_SOURCES) +if ENABLE_SECCOMP +lxc_test_rootfs_options_SOURCES += ../lxc/seccomp.c ../lxc/lxcseccomp.h +endif + +if !HAVE_STRCHRNUL +lxc_test_rootfs_options_SOURCES += ../include/strchrnul.c ../include/strchrnul.h +endif + AM_CFLAGS += -DLXCROOTFSMOUNT=\"$(LXCROOTFSMOUNT)\" \ -DLXCPATH=\"$(LXCPATH)\" \ -DLXC_GLOBAL_CONF=\"$(LXC_GLOBAL_CONF)\" \ @@ -818,6 +872,7 @@ bin_PROGRAMS = lxc-test-api-reboot \ lxc-test-parse-config-file \ lxc-test-raw-clone \ lxc-test-reboot \ + lxc-test-rootfs-options \ lxc-test-saveconfig \ lxc-test-share-ns \ lxc-test-shortlived \ @@ -925,6 +980,7 @@ EXTRA_DIST = arch_parse.c \ may_control.c \ mount_injection.c \ parse_config_file.c \ + rootfs_options.c \ saveconfig.c \ shortlived.c \ shutdowntest.c \ diff --git a/src/tests/rootfs_options.c b/src/tests/rootfs_options.c new file mode 100644 index 000000000..c103cbc11 --- /dev/null +++ b/src/tests/rootfs_options.c @@ -0,0 +1,161 @@ +/* liblxcapi + * + * Copyright © 2021 Christian Brauner . + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" + +#define __STDC_FORMAT_MACROS + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef HAVE_STATVFS +#include +#endif + +#include "lxctest.h" +#include "utils.h" + +static int has_mount_properties(const char *path, unsigned int flags) +{ +#ifdef HAVE_STATVFS + int ret; + struct statvfs sb; + + ret = statvfs(path, &sb); + if (ret < 0) + return -errno; + + if ((sb.f_flag & flags) == flags) + return 0; + + return -EINVAL; + +#else + return -EOPNOTSUPP; +#endif +} + +static int rootfs_options(void *payload) +{ + int ret; + + ret = has_mount_properties("/", + MS_NODEV | + MS_NOSUID | + MS_RDONLY); + if (ret != 0) { + if (ret == -EOPNOTSUPP) + return EXIT_SUCCESS; + + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +int main(int argc, char *argv[]) +{ + int fret = EXIT_FAILURE; + lxc_attach_options_t attach_options = LXC_ATTACH_OPTIONS_DEFAULT; + int ret; + pid_t pid; + struct lxc_container *c; + + c = lxc_container_new("rootfs-options", NULL); + if (!c) { + lxc_error("%s", "Failed to create container \"rootfs-options\""); + exit(fret); + } + + if (c->is_defined(c)) { + lxc_error("%s\n", "Container \"rootfs-options\" is defined"); + goto on_error_put; + } + + if (!c->createl(c, "busybox", NULL, NULL, 0, NULL)) { + lxc_error("%s\n", "Failed to create busybox container \"rootfs-options\""); + goto on_error_put; + } + + if (!c->is_defined(c)) { + lxc_error("%s\n", "Container \"rootfs-options\" is not defined"); + goto on_error_put; + } + + c->clear_config(c); + + if (!c->set_config_item(c, "lxc.rootfs.options", "nodev,nosuid,ro")) { + lxc_error("%s\n", "Failed to set config item \"lxc.mount.auto=sys:mixed\""); + goto on_error_put; + } + + if (!c->load_config(c, NULL)) { + lxc_error("%s\n", "Failed to load config for container \"rootfs-options\""); + goto on_error_stop; + } + + if (!c->want_daemonize(c, true)) { + lxc_error("%s\n", "Failed to mark container \"rootfs-options\" daemonized"); + goto on_error_stop; + } + + if (!c->startl(c, 0, NULL)) { + lxc_error("%s\n", "Failed to start container \"rootfs-options\" daemonized"); + goto on_error_stop; + } + + /* Leave some time for the container to write something to the log. */ + sleep(2); + + ret = c->attach(c, rootfs_options, NULL, &attach_options, &pid); + if (ret < 0) { + lxc_error("%s\n", "Failed to run function in container \"rootfs-options\""); + goto on_error_stop; + } + + ret = wait_for_pid(pid); + if (ret < 0) { + lxc_error("%s\n", "Function \"rootfs-options\" failed"); + goto on_error_stop; + } + + fret = 0; + +on_error_stop: + if (c->is_running(c) && !c->stop(c)) + lxc_error("%s\n", "Failed to stop container \"rootfs-options\""); + + if (!c->destroy(c)) + lxc_error("%s\n", "Failed to destroy container \"rootfs-options\""); + +on_error_put: + lxc_container_put(c); + exit(fret); +}