[PATCH] mount: canonicalize node before doing mount syscall

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



After mounting the filesystem, the mountpoint specified by the user
may become invalid. This happens when mounting 'through' chain of symlinks,
where at least one symlink in the chain is descendant of the final chain
target, like the structure created as follows:

cd /
mkdir dir1
ln -s . dir1/rlink
ln -s /dir1/rlink dir2

Here, the symlink chain is:
/dir2 -> /dir1/rlink -> /dir1

After "mount /dev/sdd1 /dir2", /proc/mounts contains (correct) entry
/dev/sdd1 /dir1 ext2 .....
, while /etc/mtab has (incorrect)
/dev/sdd1 /dir2 ext2 ....
The wrong entry in mtab is caused by not being able to canonicalize()
the /dir2 directory (the symlink chain has been broken by the mount(2)).

This patch solves this by doing canonicalize() prior to mount(2) in
try_mount_one() and passing the canonicalized path to
update_mtab_entry(). This fixes the inconsistency between /etc/mtab and
/proc/mounts, however, it does not fix the following:

> mount /dev/sdd1 /dir2
> umount /dir2
umount: /dir2: not found
---
 mount/mount.c |   19 ++++++++++++++-----
 1 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/mount/mount.c b/mount/mount.c
index c31892b..2be43ab 100644
--- a/mount/mount.c
+++ b/mount/mount.c
@@ -1218,7 +1218,7 @@ update_mtab_entry(const char *spec, const char *node, const char *type,
 	struct my_mntent mnt;
 
 	mnt.mnt_fsname = is_pseudo_fs(type) ? xstrdup(spec) : canonicalize(spec);
-	mnt.mnt_dir = canonicalize (node);
+	mnt.mnt_dir = node;
 	mnt.mnt_type = type;
 	mnt.mnt_opts = opts;
 	mnt.mnt_freq = freq;
@@ -1262,7 +1262,6 @@ update_mtab_entry(const char *spec, const char *node, const char *type,
 		}
 	}
 	my_free(mnt.mnt_fsname);
-	my_free(mnt.mnt_dir);
 }
 
 static void
@@ -1351,6 +1350,8 @@ try_mount_one (const char *spec0, const char *node0, const char *types0,
   /* copies for freeing on exit */
   const char *opts1, *spec1, *node1, *types1, *extra_opts1;
 
+  char *canonicalized_node = 0;
+
   if (verbose > 2) {
 	  printf("mount: spec:  \"%s\"\n", spec0);
 	  printf("mount: node:  \"%s\"\n", node0);
@@ -1414,6 +1415,12 @@ try_mount_one (const char *spec0, const char *node0, const char *types0,
 
   block_signals (SIG_BLOCK);
 
+  /* In special cases, the path stored in node can become invalid after
+   * the filesystem is mounted. So do the canonicalization prior to
+   * the actual system call.
+   */
+  canonicalized_node = canonicalize(node);
+
   if (!fake) {
     mnt5_res = guess_fstype_and_mount (spec, node, &types, flags & ~MS_NOSYS,
 				       mount_opts, &special, &status);
@@ -1430,7 +1437,8 @@ try_mount_one (const char *spec0, const char *node0, const char *types0,
    * /proc/mounts.
    */
   if (!fake && mnt5_res == 0 &&
-      (flags & MS_BIND) && (flags & MS_RDONLY) && !is_readonly(node)) {
+      (flags & MS_BIND) && (flags & MS_RDONLY) &&
+      !is_readonly(canonicalized_node)) {
 
       printf(_("mount: warning: %s seems to be mounted read-write.\n"), node);
       flags &= ~MS_RDONLY;
@@ -1442,7 +1450,7 @@ try_mount_one (const char *spec0, const char *node0, const char *types0,
    */
   if (!fake && mnt5_res == 0 &&
       !(flags & (MS_RDONLY | MS_PROPAGATION | MS_MOVE)) &&
-      is_readonly(node)) {
+      is_readonly(canonicalized_node)) {
 
       printf(_("mount: warning: %s seems to be mounted read-only.\n"), node);
       flags |= MS_RDONLY;
@@ -1453,7 +1461,7 @@ try_mount_one (const char *spec0, const char *node0, const char *types0,
 
       if (!(mounttype & MS_PROPAGATION)) {
 	      update_mtab_entry(loop ? loopfile : spec,
-			node,
+			canonicalized_node,
 			types ? types : "unknown",
 			fix_opts_string (flags & ~MS_NOMTAB, extra_opts, user),
 			flags,
@@ -1704,6 +1712,7 @@ try_mount_one (const char *spec0, const char *node0, const char *types0,
   my_free(node1);
   my_free(opts1);
   my_free(types1);
+  free(canonicalized_node);
 
   return res;
 }
-- 
1.6.4.2


Petr

--
Petr Uzel
IRC: ptr_uzl @ freenode

Attachment: pgpwJ7KWfpGZM.pgp
Description: PGP signature


[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux