Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 12 Jan 2002 03:28:44 +1100 (EST)
From:      Bruce Evans <bde@zeta.org.au>
To:        Jake Burkholder <jake@locore.ca>
Cc:        <arch@freebsd.org>, <marcel@freebsd.org>
Subject:   stackgap lossage (was: cvs commit: src/sys/i386/i386 trap.c)
Message-ID:  <20020112031708.D2622-100000@gamplex.bde.org>
In-Reply-To: <20020101121559.D9752@locore.ca>

next in thread | previous in thread | raw e-mail | index | archive | help
[Redirected from cvs-committers]

On Tue, 1 Jan 2002, Jake Burkholder wrote:

> Apparently, On Tue, Jan 01, 2002 at 04:49:17AM +1100,
> 	Bruce Evans said words to the effect of;
>
> > On Sun, 30 Dec 2001, Jake Burkholder wrote:
> >
> > > Apparently, On Sun, Dec 30, 2001 at 11:43:59AM -0800,
> > > 	Poul-Henning Kamp said words to the effect of;
> > >
> > > > phk         2001/12/30 11:43:59 PST
> > > >
> > > >   Modified files:
> > > >     sys/i386/i386        trap.c
> > > >   Log:
> > > >   GC an alternate trap_pfault() which has rotted away behind an "#ifdef notyet"
> > > >   since 21-Mar-95 .
> > > >
> > > >   Revision  Changes    Path
> > > >   1.210     +0 -118    src/sys/i386/i386/trap.c
> > >
> > > This is the one that should have been used.  The existing one is broken because
> > > it allows faults on user memory in kernel mode without using copy{in,out} or
> > > {f,s}uword.  Apparently there is still broken kernel code that expects this to
> > > work.
> >
> > I agree.  Some of the bitrot was fixed in my local version, but I never
> > got around to testing it.
> >
> > What do the other arches do?  They all seem to be based on the ancient
> > version that did trap_pfault() inline in trap().  The i386 version stopped
> > doing this in rev.1.25 (1994/06/06).
>
> The ia64 and alpha ones seem to be, yes.  But they do correctly disallow these
> faults, except for in the stackgap used by the linux emulator.  The sparc64
> version is based on the non-broken i386 one.  Special instructions must be
> used to access user space, so copy{in,out} are mandatory.

The sparc64 version is much cleaner.

I have run on i386's with faults disallowed for a while and finally
hit a problem when I tried Linux netscape.  The stackgap stuff is evil.
Pointers into the stackgap are passed to utility functions that expect
ordinary pointers.  I fixed just enough to get Linux netscape to work.
The comment has some more details.

%%%
Index: linux_signal.c
===================================================================
RCS file: /home/ncvs/src/sys/compat/linux/linux_signal.c,v
retrieving revision 1.32
diff -u -2 -r1.32 linux_signal.c
--- linux_signal.c	12 Sep 2001 08:36:57 -0000	1.32
+++ linux_signal.c	11 Jan 2002 01:04:59 -0000
@@ -85,6 +85,39 @@

 static void
-linux_to_bsd_sigaction(l_sigaction_t *lsa, struct sigaction *bsa)
+linux_to_bsd_sigaction(l_sigaction_t *lsa_xxx, struct sigaction *bsa_xxx)
 {
+	struct sigaction bsa_np;
+	l_sigaction_t lsa_np;
+	struct sigaction *bsa;
+	l_sigaction_t *lsa;
+
+	/*
+	 * XXX sigactions tend to be in the stack gap, in which case they
+	 * must be copied in or out.
+	 *
+	 * Direct accesses caused fatal pagefaults when the pagefault handler
+	 * was fixed to make pagefaults for direct accesses to user memory
+	 * fatal.  This check doesn't detect invalid accessed to pages that
+	 * have already been mapped, and copying probably weakens the check
+	 * by mapping the whole stack gap.  It's surprising that the whole
+	 * stack gap isn't always mapped by a previous copying.  Who knows
+	 * how many invalid access we don't detect.
+	 *
+	 * XXX bsa and lsa are bogusly named to avoid changing everything.
+	 *
+	 * XXX l_sigaction_t is a style violation.
+	 *
+	 * The VM_MAXUSER_ADDRESS check is a cheap (probably wrong) version
+	 * of useracc().
+	 */
+	bsa = &bsa_np;
+	bzero(bsa, sizeof(*bsa));
+	if ((uintptr_t)lsa_xxx >= VM_MAXUSER_ADDRESS)
+		lsa = lsa_xxx;
+	else {
+		lsa = &lsa_np;
+		if (copyin(lsa_xxx, lsa, sizeof(*lsa)) != 0)
+			panic("aieeee 1");
+	}

 	linux_to_bsd_sigset(&lsa->lsa_mask, &bsa->sa_mask);
@@ -105,9 +138,30 @@
 	if (lsa->lsa_flags & LINUX_SA_NOMASK)
 		bsa->sa_flags |= SA_NODEFER;
+
+	if ((uintptr_t)bsa_xxx >= VM_MAXUSER_ADDRESS)
+		*bsa_xxx = *bsa;
+	else {
+		if (copyout(bsa, bsa_xxx, sizeof(*bsa_xxx)) != 0)
+			panic("aieeee 2");
+	}
 }

 static void
-bsd_to_linux_sigaction(struct sigaction *bsa, l_sigaction_t *lsa)
+bsd_to_linux_sigaction(struct sigaction *bsa_xxx, l_sigaction_t *lsa_xxx)
 {
+	struct sigaction bsa_np;
+	l_sigaction_t lsa_np;
+	struct sigaction *bsa;
+	l_sigaction_t *lsa;
+
+	if ((uintptr_t)bsa_xxx >= VM_MAXUSER_ADDRESS)
+		bsa = bsa_xxx;
+	else {
+		bsa = &bsa_np;
+		if (copyin(bsa_xxx, bsa, sizeof(*bsa)) != 0)
+			panic("aieeee 3");
+	}
+	lsa = &lsa_np;
+	bzero(lsa, sizeof(*lsa));

 	bsd_to_linux_sigset(&bsa->sa_mask, &lsa->lsa_mask);
@@ -129,4 +183,11 @@
 	if (bsa->sa_flags & SA_NODEFER)
 		lsa->lsa_flags |= LINUX_SA_NOMASK;
+
+	if ((uintptr_t)lsa_xxx >= VM_MAXUSER_ADDRESS)
+		*lsa_xxx = *lsa;
+	else {
+		if (copyout(lsa, lsa_xxx, sizeof(*lsa_xxx)) != 0)
+			panic("aieeee 3");
+	}
 }

%%%

Bruce


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-arch" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020112031708.D2622-100000>