]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: add post-mount checks to detect ro/rw
authorKarel Zak <kzak@redhat.com>
Mon, 16 Jan 2012 11:09:36 +0000 (12:09 +0100)
committerKarel Zak <kzak@redhat.com>
Mon, 16 Jan 2012 11:09:36 +0000 (12:09 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
libmount/src/context_loopdev.c
libmount/src/context_mount.c
libmount/src/mountP.h
libmount/src/utils.c

index 8e9ed93aa5bb8d7ca74d31d2cd67029e2e270238..a379587090db486a5c6da93d77646b906c5d0185 100644 (file)
@@ -289,8 +289,7 @@ int mnt_context_setup_loopdev(struct libmnt_context *cxt)
                         * mount planned read-write, but loopdev is read-only,
                         * let's fix mount options...
                         */
-                       cxt->mountflags |= MS_RDONLY;
-
+                       mnt_context_set_mflags(cxt, cxt->mountflags | MS_RDONLY);
 
                /* we have to keep the device open until mount(1),
                 * otherwise it will auto-cleared by kernel
index 6f2a3dc116dca6ff59ac42e52358ac1253f0452b..9d5933c5644544c2a0184a8cdc0ae18f79b9c1a3 100644 (file)
@@ -455,10 +455,6 @@ static int do_mount(struct libmnt_context *cxt, const char *try_type)
                        rc = mnt_fs_set_fstype(fs, try_type);
        }
 
-       /* TODO: check if the result is really read-only/read-write
-        *       and if necessary update cxt->mountflags
-        */
-
        return rc;
 }
 
@@ -591,6 +587,7 @@ int mnt_context_prepare_mount(struct libmnt_context *cxt)
 int mnt_context_do_mount(struct libmnt_context *cxt)
 {
        const char *type;
+       int res;
 
        assert(cxt);
        assert(cxt->fs);
@@ -607,9 +604,40 @@ int mnt_context_do_mount(struct libmnt_context *cxt)
 
        type = mnt_fs_get_fstype(cxt->fs);
        if (type)
-               return do_mount(cxt, NULL);
+               res = do_mount(cxt, NULL);
+       else
+               res = do_mount_by_pattern(cxt, cxt->fstype_pattern);
+
+       if (mnt_context_get_status(cxt)
+           && !(cxt->flags & MNT_FL_FAKE)
+           && !cxt->helper) {
+               /*
+                * Mounted by mount(2), do some post-mount checks
+                *
+                * Kernel allows to use MS_RDONLY for bind mounts, but the
+                * read-only request could be silently ignored. Check it to
+                * avoid 'ro' in mtab and 'rw' in /proc/mounts.
+                */
+               if ((cxt->mountflags & MS_BIND)
+                   && (cxt->mountflags & MS_RDONLY)
+                   && !mnt_is_readonly(mnt_context_get_target(cxt)))
+
+                       mnt_context_set_mflags(cxt,
+                                       cxt->mountflags & ~MS_RDONLY);
+
+
+               /* Kernel can silently add MS_RDONLY flag when mounting file
+                * system that does not have write support. Check this to avoid
+                * 'ro' in /proc/mounts and 'rw' in mtab.
+                */
+               if (!(cxt->mountflags & (MS_RDONLY | MS_PROPAGATION | MS_MOVE))
+                   && mnt_is_readonly(mnt_context_get_target(cxt)))
+
+                       mnt_context_set_mflags(cxt,
+                                       cxt->mountflags | MS_RDONLY);
+       }
 
-       return do_mount_by_pattern(cxt, cxt->fstype_pattern);
+       return res;
 }
 
 /**
index c321702b68766f03732cc5af82c7d227aafdae0e..05a13d5de6f64adb386c0278e46d6c528f6f949d 100644 (file)
@@ -129,6 +129,8 @@ extern int mnt_run_test(struct libmnt_test *tests, int argc, char *argv[]);
 extern int endswith(const char *s, const char *sx);
 extern int startswith(const char *s, const char *sx);
 
+extern int mnt_is_readonly(const char *path);
+
 extern int mnt_parse_offset(const char *str, size_t len, uintmax_t *res);
 
 extern int mnt_chdir_to_parent(const char *target, char **filename);
index b3bb8dce458c0edc1164139e78f6677923b715c1..cbaabc6c4c948d9642ae92f3446290cf895682e9 100644 (file)
@@ -145,6 +145,41 @@ err:
        return rc;
 }
 
+/*
+ * Check if @path is on read-only filesystem independently on file permissions.
+ */
+int mnt_is_readonly(const char *path)
+{
+       if (access(path, W_OK) == 0)
+               return 0;
+       if (errno == EROFS)
+               return 1;
+       if (errno != EACCES)
+               return 0;
+
+#ifdef HAVE_FUTIMENS
+       /*
+        * access(2) returns EACCES on read-only FS:
+        *
+        * - for set-uid application if one component of the path is not
+        *   accessible for the current rUID. (Note that euidaccess(2) does not
+        *   check for EROFS at all).
+        *
+        * - for read-write filesystem with read-only VFS node (aka -o remount,ro,bind)
+        */
+       {
+               struct timespec times[2];
+
+               times[0].tv_nsec = UTIME_NOW;   /* atime */
+               times[1].tv_nsec = UTIME_OMIT;  /* mtime */
+
+               if (utimensat(AT_FDCWD, path, times, 0) == -1)
+                       return errno == EROFS;
+       }
+#endif
+       return 0;
+}
+
 /**
  * mnt_mangle:
  * @str: string