From: Serge Hallyn Date: Wed, 20 Aug 2014 23:18:40 +0000 (+0000) Subject: lxc_mount_auto_mounts: honor existing nodev etc at remounts X-Git-Tag: lxc-1.1.0.alpha2~57 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e2a7e8dc47df0f188f89e0ef9945c49f126e5475;p=thirdparty%2Flxc.git lxc_mount_auto_mounts: honor existing nodev etc at remounts Same problem as we had with mount_entry(). lxc_mount_auto_mounts() sometimes does bind mount followed by remount to change options. With recent kernels it must pass any preexisting NODEV/NOSUID/etc flags. Signed-off-by: Serge Hallyn Acked-by: Stéphane Graber --- diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 072623bd8..d98009b17 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -689,6 +689,39 @@ int pin_rootfs(const char *rootfs) return fd; } +/* + * If we are asking to remount something, make sure that any + * NOEXEC etc are honored. + */ +static unsigned long add_required_remount_flags(const char *s, const char *d, + unsigned long flags) +{ + struct statvfs sb; + unsigned long required_flags = 0; + + if (!(flags & MS_REMOUNT)) + return flags; + + if (!s) + s = d; + + if (!s) + return flags; + if (statvfs(s, &sb) < 0) + return flags; + + if (sb.f_flag & MS_NOSUID) + required_flags |= MS_NOSUID; + if (sb.f_flag & MS_NODEV) + required_flags |= MS_NODEV; + if (sb.f_flag & MS_RDONLY) + required_flags |= MS_RDONLY; + if (sb.f_flag & MS_NOEXEC) + required_flags |= MS_NOEXEC; + + return flags | required_flags; +} + static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_handler *handler) { int r; @@ -729,6 +762,7 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha char *source = NULL; char *destination = NULL; int saved_errno; + unsigned long mflags; if (default_mounts[i].source) { /* will act like strdup if %r is not present */ @@ -749,10 +783,12 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha return -1; } } - r = mount(source, destination, default_mounts[i].fstype, default_mounts[i].flags, default_mounts[i].options); + mflags = add_required_remount_flags(source, destination, + default_mounts[i].flags); + r = mount(source, destination, default_mounts[i].fstype, mflags, default_mounts[i].options); saved_errno = errno; if (r < 0) - SYSERROR("error mounting %s on %s", source, destination); + SYSERROR("error mounting %s on %s flags %lu", source, destination, mflags); free(source); free(destination); if (r < 0) {