From andreas@syndrom23.de  Thu Dec  1 02:57:14 2005
Return-Path: <andreas@syndrom23.de>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 1A1F516A41F;
	Thu,  1 Dec 2005 02:57:14 +0000 (GMT)
	(envelope-from andreas@syndrom23.de)
Received: from vs159088.vserver.de (syndrom23.de [62.75.159.88])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 620BB43D55;
	Thu,  1 Dec 2005 02:57:12 +0000 (GMT)
	(envelope-from andreas@syndrom23.de)
Received: from xentros.syndrom23.de ([212.204.44.203])
	(authenticated bits=0)
	by vs159088.vserver.de (8.12.8/8.12.8) with ESMTP id jB12ux4T027236;
	Thu, 1 Dec 2005 03:57:07 +0100
Message-Id: <1133405840.0@xentros.syndrom23.de>
Date: Thu, 1 Dec 2005 03:57:20 +0100
From: "Andreas Kohn" <andreas@syndrom23.de>
To: "FreeBSD gnats submit" <FreeBSD-gnats-submit@freebsd.org>
Cc: rodrigc@freebsd.org
Subject: [PATCH] avoid double mounts if the mount point is a symlink
X-Send-Pr-Version: gtk-send-pr 0.4.6 
X-GNATS-Notify:

>Number:         89782
>Category:       bin
>Synopsis:       [patch] mount(8): avoid double mounts if the mount point is a symlink
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    pjd
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Dec 01 03:00:13 GMT 2005
>Closed-Date:    Tue Jan 24 15:28:04 GMT 2006
>Last-Modified:  Tue Jan 24 15:28:04 GMT 2006
>Originator:     Andreas Kohn
>Release:        FreeBSD 7.0-CURRENT i386
>Organization:
>Environment:


System: FreeBSD 7.0-CURRENT #6: Tue Nov 29 03:37:45 CET 2005
    root@xentros.syndrom23.de:/usr/obj/usr/src/sys/XENTROS



>Description:


My /etc/fstab contains the following line
linprocfs /compat/linux/proc linprocfs ....,
which is suggested by java/jdk15 port for instance.

mount checks if a file system is mounted before mounting it with
mount -a and others, but doesn't consider symlinks. /compat is a link to /usr/compat, and so the check in ismounted() does not detect that linprocfs is mounted, and will mount it twice if mount -a is called twice.
This could for example happen if you boot to single user, mount -a your devices and then exit single user mode to multiuser mode (somewhere in the process mount -a will be called).


>How-To-Repeat:


Add a line to /etc/fstab that has a mountpoint that is a symlink.
Call mount /this/mountpoint multiple times, and observe that this mount is shown multiple times in mount output.



>Fix:


The fix here uses realpath to resolve the mountpoint from /etc/fstab
into a non-symlink path, and compares that path to struct statfs->f_mntonname. It fixes the problem for me. 

Alternative approaches would be to discourage the use of symlinks for mountpoints. This would then require to rewrite all ports that use /compat/linux instead of /usr/compat/linux etc.

rodrigc@ Cc'ed, because he was working on mount recently. I do not know if this repeated mounting may be a regression.

--- mount-symlinks.diff begins here ---
Index: sbin/mount/mount.c
===================================================================
RCS file: /storage/freebsd/cvs/src/sbin/mount/mount.c,v
retrieving revision 1.76
diff -u -r1.76 mount.c
--- sbin/mount/mount.c	24 Nov 2005 17:35:05 -0000	1.76
+++ sbin/mount/mount.c	30 Nov 2005 17:21:14 -0000
@@ -392,13 +392,18 @@
 ismounted(struct fstab *fs, struct statfs *mntbuf, int mntsize)
 {
 	int i;
+	char realfsfile[PATH_MAX];
 
 	if (fs->fs_file[0] == '/' && fs->fs_file[1] == '\0')
 		/* the root file system can always be remounted */
 		return (0);
 
+	/* The user may have specified a symlink in fstab, resolve the path */
+	if (realpath(fs->fs_file, realfsfile) == NULL)
+	    err(1, "%s cannot be resolved to a path", fs->fs_file);
+
 	for (i = mntsize - 1; i >= 0; --i)
-		if (strcmp(fs->fs_file, mntbuf[i].f_mntonname) == 0 &&
+		if (strcmp(realfsfile, mntbuf[i].f_mntonname) == 0 &&
 		    (!isremountable(fs->fs_vfstype) ||
 		     strcmp(fs->fs_spec, mntbuf[i].f_mntfromname) == 0))
 			return (1);
--- mount-symlinks.diff ends here ---



>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->pjd 
Responsible-Changed-By: pjd 
Responsible-Changed-When: Tue Jan 17 13:39:55 UTC 2006 
Responsible-Changed-Why:  
I'll take this one. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=89782 
State-Changed-From-To: open->patched 
State-Changed-By: pjd 
State-Changed-When: Wed Jan 18 11:00:51 UTC 2006 
State-Changed-Why:  
Fix committed to HEAD. MFC after 3 days. 
Thanks! 

http://www.freebsd.org/cgi/query-pr.cgi?pr=89782 
State-Changed-From-To: patched->closed 
State-Changed-By: pjd 
State-Changed-When: Tue Jan 24 15:27:45 UTC 2006 
State-Changed-Why:  
Patch MFCed to RELENG_6. Thanks. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=89782 
>Unformatted:
