]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
lxc_mount_auto_mounts: honor existing nodev etc at remounts
authorSerge Hallyn <serge.hallyn@ubuntu.com>
Wed, 20 Aug 2014 23:18:40 +0000 (23:18 +0000)
committerStéphane Graber <stgraber@ubuntu.com>
Fri, 22 Aug 2014 19:05:37 +0000 (14:05 -0500)
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 <serge.hallyn@ubuntu.com>
Acked-by: Stéphane Graber <stgraber@ubuntu.com>
src/lxc/conf.c

index 072623bd8f3c3db45d0b449d580452b797da2220..d98009b1793c1e536cf3af90b35c508dbce7bb37 100644 (file)
@@ -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) {