Subject: Re: emul vs. symlinks
To: Bill Studenmund <wrstuden@netbsd.org>
From: Quentin Garnier <cube@NetBSD.org>
List: tech-kern
Date: 07/13/2004 23:25:21
--Signature=_Tue__13_Jul_2004_23_25_21_+0200_7UfCKGLnm.brDI=1
Content-Type: text/plain; charset=US-ASCII
Content-Disposition: inline
Content-Transfer-Encoding: 7bit

Le Mon, 12 Jul 2004 13:13:40 -0700
Bill Studenmund a ecrit :
> On Sat, Jul 10, 2004 at 11:05:25AM +0200, Quentin Garnier wrote:
> > Le Fri, 9 Jul 2004 19:00:44 -0700
> > Bill Studenmund a ecrit :
[...]
> > > I really think that you don't need to add your own namei() routine.
> > > Since you can tell namei() to not follow symlinks and the symlink
> > > following isn't hard, just do it yourself.
> > 
> > Well, what namei() does is exactly that:  call lookup() and handle
> > symlinks when it returns.  As ugly as it might be, it's easier to
> > start from namei() than from scratch.
> 
> Yes, but namei() does more than that.

What more does it do?  Let's see.

o It takes care of copyinstr()ing if UIO_SYSSPACE is not given.  I guess
  I can remove that test in compat_namei, since I know where I call from.

o It has a ktrace/systrace point.  It might be avoided, although I think
  it can be useful in ktrace.  I don't know about how it could be useful
  with systrace, though, since you don't really know you're in
  compat_namei.

o I can leave the LOCKPARENT test after lookup()

o I need all the rest.

In the end it's clear that I want that modified namei() (however we obtain
it).

> My main objection is to having two almost-the-same copies of the same 
> code. While I'd rather not tweak namei() much, I think I'd rather
> shuffle the code around than make two copies of it.

I agree.

> My suspicion is that we want to change all calls to namei() into calls 
> that indirect off of a pointer in the emulation. The NetBSD emulation 
> points to namei(), while all emulations that play with pathing point to 
> emul_namei().

Actually, that's not true.  We only want the significant calls to go
through the emulated layer, as Matthew (I think) pointed out when I first
brought up the subject.  We want stuff that search for libraries to look
at the right place, so obviously open() has to search into the emulation
root.  But other things don't, such as stat().  At least in netbsd32, we
don't need it to load libraries and binaries, so we don't need it to go
through emul_find().

> emul_namei() looks at the first four bytes of the path. If they are 
> "/../" then it does "return namei(ndp);".
> 
> Then it does a namei lookup of "/emul/foo". If this lookup fails, 
> emul_namei() just does a "return namei(ndp);". i.e. if you don't have 
> /emul/foo, then we short-circuit the special path lookup.
> 
> Then what I want us to do (which I admit needs some work) is to try the 
> namei() lookup with the result of the above lookup ("/emul/foo") as a 
> temporary process root (the fact it should really be a call-specific
> root is what needs work). If it fails, then perform the lookup with the
> real process root. Oh, we do the above namei() lookup with the "don't
> follow any symlinks" flag set. 
> 
> If we found a symlink and either it wasn't terminal or we are following 
> symlinks then we do:
> 
> 	while (we found a symlink) {
> 		numsymlinks++;
> 		if (too many symlinks)
> 			return ELOOP;
> 		set "chroot" to "/emul/foo" result
> 		error = namei(ndp);
> 		if ((is absolute path) && (error == ENOENT)) {
> 			set "chroot" to normal chroot
> 			error = namei(ndp);
> 		}
> 	}

That's basically what my modified namei() does, except that the chroot
game is done inside namei() itself.

> A similar option would be to leave namei() alone, but turn it into
> namei() and namei1(). namei() would do some setup, then in the normal
> case just call namei1(). In the emulation case, it would call
> namei_emul() which would do the above dance (changed slightly as needed)
> and call namei1().
> 
> Hmmm... Maybe having two versions is what we need.

I think that in the end, that always what we'll have, for the simple
reason that we cannot allow ourselves to permanently slow down namei()
(even by a single test) for the sake of taking care of emulated binaries
that we won't run most of the time.

> I think if we do this right, we can get rid of emul_find().

Well, I'm not so sure about this, since it's syscall-dependent.  Arguably
we could flag some way the calling lwp.

-- 
Quentin Garnier - cube@NetBSD.org
The NetBSD Project - http://www.NetBSD.org/

--Signature=_Tue__13_Jul_2004_23_25_21_+0200_7UfCKGLnm.brDI=1
Content-Type: application/pgp-signature

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (NetBSD)

iQEVAwUBQPRTRtgoQloHrPnoAQLSgwf/eU3DGWRfjoosx673s6QewSn2tO5zIzX+
wIsFj7L5Hx1xIkHVfoftoiFTW4OMwt7/ooWuaFpxi5wbePl1a8sfktuNWiB1hhlN
Dw2s3q1oc/fycw7veJd3BEIiagp7R/lfheWrsWLzcUDnFQWp9UH3IzOfyPnsTNY5
RpG1akLb8uheKGmGpnAO9gT0HD6ZsgNftLL07BI3TkiCxeAGB+46sNvuvzt3+C3b
ftVCHH2e06aoK3BVezlCCgoSJfQFMRNH7L+kYXixQkL0qVYcg9QoGracjDhYo337
X6ZUbuVWGU2TvY9GbpaQ1qD4ZXcZhM01NQiSEBHE8qboTb/F+5DoRA==
=wJiy
-----END PGP SIGNATURE-----

--Signature=_Tue__13_Jul_2004_23_25_21_+0200_7UfCKGLnm.brDI=1--