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>
