From avg@oddity.topspin.kiev.ua  Wed Nov 10 15:46:30 2004
Return-Path: <avg@oddity.topspin.kiev.ua>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 213BC16A4D0
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 10 Nov 2004 15:46:30 +0000 (GMT)
Received: from citadel.icyb.net.ua (citadel.icyb.net.ua [212.40.38.140])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 5413843D4C
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 10 Nov 2004 15:44:43 +0000 (GMT)
	(envelope-from avg@oddity.topspin.kiev.ua)
Received: from oddity.topspin.kiev.ua (oddity.topspin.kiev.ua [212.40.38.87])
	by citadel.icyb.net.ua (8.8.8p3/ICyb-2.3exp) with ESMTP id RAA05217
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 10 Nov 2004 17:19:17 +0200 (EET)
	(envelope-from avg@oddity.topspin.kiev.ua)
Received: from oddity.topspin.kiev.ua (localhost [127.0.0.1])
	by oddity.topspin.kiev.ua (8.12.10/8.12.10) with ESMTP id iAAFJGpb006683
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 10 Nov 2004 17:19:16 +0200 (EET)
	(envelope-from avg@oddity.topspin.kiev.ua)
Received: (from avg@localhost)
	by oddity.topspin.kiev.ua (8.12.10/8.12.10/Submit) id iAAFJGbf006682;
	Wed, 10 Nov 2004 17:19:16 +0200 (EET)
	(envelope-from avg)
Message-Id: <200411101519.iAAFJGbf006682@oddity.topspin.kiev.ua>
Date: Wed, 10 Nov 2004 17:19:16 +0200 (EET)
From: Andriy Gapon <avg@icyb.net.ua>
To: FreeBSD-gnats-submit@freebsd.org
Subject: linux emulation: root dir special handling useless and harmful
X-Send-Pr-Version: 3.113

>Number:         73777
>Category:       kern
>Synopsis:       [linux] [patch] linux emulation: root dir special handling useless and harmful
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-emulation
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Nov 10 15:50:29 GMT 2004
>Closed-Date:    Sun Dec 05 15:29:06 UTC 2010
>Last-Modified:  Sun Dec 05 15:29:06 UTC 2010
>Originator:     Andriy Gapon
>Release:        FreeBSD 5.2.1-RELEASE-p11 i386
>Organization:
>Environment:
System:
FreeBSD 4.X, 5.X
linux_base-7.1_7
	
>Description:
A little background: in linux emulation any access to file system node is first
tried with "/compt/linux" prepended to its path, original path is tried only
if linuxified path is not vaiable. In that fashion linux applications can
access both files under linux emulation root (/compat/linux) and those files
under the real root that are not shadowed by the former files. This behavior
is reverted only for one filesystem node - "/compat/linux" itself. That is,
no application under linux emualtion is able to access linux compatibility
root, real root ("/") is given to it instead.
This seems to be illogical, linux application is probably more ineterested
in linux root directory rather than real root directory. Also, no linux 
application should ever want to "break out" from linux root by "cd ..".

So I think that the special handling for root directories should be removed
and real root directory should be shadowed by /compat/linux.

Existing linux emulation behavior also breaks "mkdir -p" from linux base 7, if
you want to creat a directory with more than one path unexstistant component:
in this case mkdir first performs chdir("/") and then iterativly mkdir()s and
chdir()s to subdirectories. So, the first action, chdir("/") would chdir to
real root and directory created either will be wrong one or will not be
created at all because of permissions.

Please also see my attemps to discuss this issue on mailing lists:
http://docs.freebsd.org/cgi/mid.cgi?4178DBA0.8050605
http://docs.freebsd.org/cgi/mid.cgi?4176A6C0.5070408

I have applied the patch attached on my system and have not seen any
problems with linux emulation, only improvements.
I run oracle 9, ibm websphere 5.1 with mq and wemps.

	
>How-To-Repeat:
1. work as unpriviledged user with shell /compat/linux/bin/bash
2. make sure /var and /compat/linux/var are different directories
3. create /compat/linux/var/foo directory with rwx permission for the user
   mentioned in step 1.
4. make sure there is no /var/foo directory
5. execute "mkdir -p /var/foo/1/2/3" as user from step 1.
6. see the above command fail with permission denied error
7. apply the attached patch
8. recompile kernel and/or linux.ko, reboot
9. try the same again
10. see successful creation of expected directory

	
>Fix:

	

--- rootdir.patch begins here ---
--- sys/compat/linux/linux_util.c.orig	Sun Nov  7 15:34:58 2004
+++ sys/compat/linux/linux_util.c	Sun Nov  7 15:53:20 2004
@@ -95,9 +95,6 @@
 	int		  cflag;
 {
 	struct nameidata	 nd;
-	struct nameidata	 ndroot;
-	struct vattr		 vat;
-	struct vattr		 vatroot;
 	int			 error;
 	const char		*prefix;
 	char			*ptr, *buf, *cp;
@@ -150,55 +147,12 @@
 
 		if ((error = namei(&nd)) != 0)
 			goto keeporig;
-
-		/*
-		 * We now compare the vnode of the linux_root to the one
-		 * vnode asked. If they resolve to be the same, then we
-		 * ignore the match so that the real root gets used.
-		 * This avoids the problem of traversing "../.." to find the
-		 * root directory and never finding it, because "/" resolves
-		 * to the emulation root directory. This is expensive :-(
-		 */
-		NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path,
-		       td);
-
-		if ((error = namei(&ndroot)) != 0) {
-			/* Cannot happen! */
-			NDFREE(&nd, NDF_ONLY_PNBUF);
-			vrele(nd.ni_vp);
-			goto keeporig;
-		}
-
-		if ((error = VOP_GETATTR(nd.ni_vp, &vat, td->td_ucred, td)) != 0) {
-			goto bad;
-		}
-
-		if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, td->td_ucred, td))
-		    != 0) {
-			goto bad;
-		}
-
-		if (vat.va_fsid == vatroot.va_fsid &&
-		    vat.va_fileid == vatroot.va_fileid) {
-			error = ENOENT;
-			goto bad;
-		}
-
 	}
 
 	NDFREE(&nd, NDF_ONLY_PNBUF);
 	vrele(nd.ni_vp);
-	if (!cflag) {
-		NDFREE(&ndroot, NDF_ONLY_PNBUF);
-		vrele(ndroot.ni_vp);
-	}
 	return error;
 
-bad:
-	NDFREE(&ndroot, NDF_ONLY_PNBUF);
-	vrele(ndroot.ni_vp);
-	NDFREE(&nd, NDF_ONLY_PNBUF);
-	vrele(nd.ni_vp);
 keeporig:
 	/* Keep the original path; copy it back to the start of the buffer. */
 	bcopy(ptr, buf, len);
--- rootdir.patch ends here ---


>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->emulation 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Mon Nov 29 09:29:49 GMT 2004 
Responsible-Changed-Why:  
Reassign to appropriate mailing list. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=73777 

From: Volker <volker@vwsoft.com>
To: bug-followup@FreeBSD.org, avg@icyb.net.ua
Cc:  
Subject: Re: kern/73777: [linux] [patch] linux emulation: root dir special
 handling useless and harmful
Date: Fri, 22 Feb 2008 22:16:02 +0100

 Andriy,
 
 I'm sorry to see your PR being in GNATS for years. I've checked your
 issue and was not able to get your patch into sync with current RELENG_7
 sources.
 
 I'm wondering if you're still thinking, the issue is real and am willing
 to send in new patches? If you think this issue has been solved in the
 meantime, please report back so we can close this PR.
 
 Thanks!
State-Changed-From-To: open->feedback 
State-Changed-By: linimon 
State-Changed-When: Sat Feb 23 03:10:25 UTC 2008 
State-Changed-Why:  
Note that submitter has been asked for feedback. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=73777 

From: Andriy Gapon <avg@icyb.net.ua>
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/73777: [linux] [patch] linux emulation: root dir special
 handling useless and harmful
Date: Sat, 23 Feb 2008 09:46:53 +0200

 This is a multi-part message in MIME format.
 --------------080104050205040809080106
 Content-Type: text/plain; charset=UTF-8
 Content-Transfer-Encoding: 7bit
 
 
 Well, I think that the issue described in this PR still holds.
 On the other hand, I now think that some people might still prefer
 current behavior over what I suggest. There could be some POLA concerns too.
 Another concern is that now the code is common to all emulation, so it's
 not linux specific anymore.
 In any case, I am attaching a patch that I currently use.
 
 -- 
 Andriy Gapon
 
 --------------080104050205040809080106
 Content-Type: text/x-patch;
  name="rootdir-6.patch"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline;
  filename="rootdir-6.patch"
 
 --- sys/kern/vfs_lookup.c.orig	Fri May 12 16:03:41 2006
 +++ sys/kern/vfs_lookup.c	Fri May 12 16:09:31 2006
 @@ -955,7 +955,7 @@
  kern_alternate_path(struct thread *td, const char *prefix, char *path,
      enum uio_seg pathseg, char **pathbuf, int create)
  {
 -	struct nameidata nd, ndroot;
 +	struct nameidata nd;
  	char *ptr, *buf, *cp;
  	size_t len, sz;
  	int error;
 @@ -1014,28 +1014,6 @@
  		error = namei(&nd);
  		if (error != 0)
  			goto keeporig;
 -
 -		/*
 -		 * We now compare the vnode of the prefix to the one
 -		 * vnode asked. If they resolve to be the same, then we
 -		 * ignore the match so that the real root gets used.
 -		 * This avoids the problem of traversing "../.." to find the
 -		 * root directory and never finding it, because "/" resolves
 -		 * to the emulation root directory. This is expensive :-(
 -		 */
 -		NDINIT(&ndroot, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, prefix,
 -		    td);
 -
 -		/* We shouldn't ever get an error from this namei(). */
 -		error = namei(&ndroot);
 -		if (error == 0) {
 -			if (nd.ni_vp == ndroot.ni_vp)
 -				error = ENOENT;
 -
 -			NDFREE(&ndroot, NDF_ONLY_PNBUF);
 -			vrele(ndroot.ni_vp);
 -			VFS_UNLOCK_GIANT(NDHASGIANT(&ndroot));
 -		}
  	}
  
  	NDFREE(&nd, NDF_ONLY_PNBUF);
 
 --------------080104050205040809080106--

From: Andriy Gapon <avg@icyb.net.ua>
To: bug-followup@FreeBSD.org
Cc: Alexander Leidinger <Alexander@leidinger.net>
Subject: Re: kern/73777: [linux] [patch] linux emulation: root dir special
 handling useless and harmful
Date: Mon, 03 Mar 2008 22:14:40 +0200

 This is a multi-part message in MIME format.
 --------------050001090401010706020209
 Content-Type: text/plain; charset=UTF-8
 Content-Transfer-Encoding: 7bit
 
 
 An updated patch that makes the proposed behavior controlled by sysctl.
 Present behavior is the default.
 
 
 -- 
 Andriy Gapon
 
 --------------050001090401010706020209
 Content-Type: text/x-patch;
  name="rootdir-7.patch"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline;
  filename="rootdir-7.patch"
 
 --- sys/kern/vfs_lookup.c.orig	2007-09-21 13:16:56.000000000 +0300
 +++ sys/kern/vfs_lookup.c	2008-03-03 22:03:16.000000000 +0200
 @@ -96,6 +96,11 @@
  SYSCTL_INT(_vfs, OID_AUTO, lookup_shared, CTLFLAG_RW, &lookup_shared, 0,
      "Enables/Disables shared locks for path name translation");
  
 +static int alt_root_is_real_root = 1;
 +SYSCTL_INT(_vfs, OID_AUTO, alt_root_is_real_root, CTLFLAG_RW,
 +    &alt_root_is_real_root, 0,
 +    "Alternative/emulation root directory resolves to the real root");
 +
  /*
   * Convert a pathname into a pointer to a locked vnode.
   *
 @@ -1071,26 +1076,28 @@
  		if (error != 0)
  			goto keeporig;
  
 -		/*
 -		 * We now compare the vnode of the prefix to the one
 -		 * vnode asked. If they resolve to be the same, then we
 -		 * ignore the match so that the real root gets used.
 -		 * This avoids the problem of traversing "../.." to find the
 -		 * root directory and never finding it, because "/" resolves
 -		 * to the emulation root directory. This is expensive :-(
 -		 */
 -		NDINIT(&ndroot, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, prefix,
 -		    td);
 -
 -		/* We shouldn't ever get an error from this namei(). */
 -		error = namei(&ndroot);
 -		if (error == 0) {
 -			if (nd.ni_vp == ndroot.ni_vp)
 -				error = ENOENT;
 -
 -			NDFREE(&ndroot, NDF_ONLY_PNBUF);
 -			vrele(ndroot.ni_vp);
 -			VFS_UNLOCK_GIANT(NDHASGIANT(&ndroot));
 +		if (alt_root_is_real_root) {
 +			/*
 +			 * We now compare the vnode of the prefix to the one
 +			 * vnode asked. If they resolve to be the same, then we
 +			 * ignore the match so that the real root gets used.
 +			 * This avoids the problem of traversing "../.." to find the
 +			 * root directory and never finding it, because "/" resolves
 +			 * to the emulation root directory. This is expensive :-(
 +			 */
 +			NDINIT(&ndroot, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, prefix,
 +			    td);
 +
 +			/* We shouldn't ever get an error from this namei(). */
 +			error = namei(&ndroot);
 +			if (error == 0) {
 +				if (nd.ni_vp == ndroot.ni_vp)
 +					error = ENOENT;
 +
 +				NDFREE(&ndroot, NDF_ONLY_PNBUF);
 +				vrele(ndroot.ni_vp);
 +				VFS_UNLOCK_GIANT(NDHASGIANT(&ndroot));
 +			}
  		}
  	}
  
 
 --------------050001090401010706020209--
State-Changed-From-To: feedback->open 
State-Changed-By: vwe 
State-Changed-When: Sun May 18 09:22:03 UTC 2008 
State-Changed-Why:  

feedback and new patch provided 

http://www.freebsd.org/cgi/query-pr.cgi?pr=73777 
State-Changed-From-To: open->closed 
State-Changed-By: avg 
State-Changed-When: Sun Dec 5 15:28:19 UTC 2010 
State-Changed-Why:  
It seems that the suggested change is not really useful 
for general FreeBSD user base. 
And I have no use for it now as well. 

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