Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 18 Aug 2011 00:10:48 +0300
From:      Kostik Belousov <kostikbel@gmail.com>
To:        Andriy Gapon <avg@freebsd.org>
Cc:        freebsd-hackers@freebsd.org, freebsd-jail@freebsd.org, Steven Hartland <killing@multiplay.co.uk>, freebsd-stable@freebsd.org
Subject:   Re: debugging frequent kernel panics on 8.2-RELEASE
Message-ID:  <20110817211048.GZ17489@deviant.kiev.zoral.com.ua>
In-Reply-To: <4E4C22D6.6070407@FreeBSD.org>
References:  <796FD5A096DE4558B57338A8FA1E125B@multiplay.co.uk> <4E491D01.1090902@FreeBSD.org> <570C5495A5E242F7946E806CA7AC5D68@multiplay.co.uk> <4E4AD35C.7020504@FreeBSD.org> <6A7238AED44542A880B082A40304D940@multiplay.co.uk> <4E4BA21F.6010805@FreeBSD.org> <581C95046B0948FC82D6F2E86948F87B@multiplay.co.uk> <4E4BBA7F.30907@FreeBSD.org> <88A6CE3E8B174E0694A3A9A5283479B4@multiplay.co.uk> <4E4C22D6.6070407@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help

--MPHowW9WJBu+8Ajw
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

On Wed, Aug 17, 2011 at 11:21:42PM +0300, Andriy Gapon wrote:
[skip]

> But I also would like to use this opportunity to discuss how we can
> make it easier to debug such issue as this. I think that this problem
> demonstrates that when we treat certain junk in kernel address value
> as a userland address value, we throw additional heaps of irrelevant
> stuff on top of an actual problem. One solution could be to use a
> special flag that would mark all actual attempts to access userland
> address (e.g. setting the flag on entrance to copyin and clearing it
> upon return), so that in the page fault handler we could distinguish
> actual faults on userland addresses from faults on garbage kernel
> addresses. I am sure that there could be other clever techniques to
> catch such garbage addresses early.

We already have such mechanism, the kernel code aware of the usermode
page access sets pcb_onfault. See the end of trap_pfault() handler.
In fact, we can catch it earlier, before even calling vm_fault().

BTW, I think this is esp. useful in the combination with the support
for the SMEP in recent Intel CPUs.

commit 2e1b36fa93f9499e37acf04a66ff0646d4f13536
Author: Konstantin Belousov <kostik@pooma.home>
Date:   Thu Aug 18 00:08:50 2011 +0300

    Assert that the exiting process does not return to usermode.
    On x86, do not call vm_fault() when the kernel is not prepared
    to handle unsuccessful page fault.

diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
index 4e5f8b8..55e1e5a 100644
--- a/sys/amd64/amd64/trap.c
+++ b/sys/amd64/amd64/trap.c
@@ -674,6 +674,19 @@ trap_pfault(frame, usermode)
 			goto nogo;
=20
 		map =3D &vm->vm_map;
+
+		/*
+		 * When accessing a usermode address, kernel must be
+		 * ready to accept the page fault, and provide a
+		 * handling routine.  Since accessing the address
+		 * without the handler is a bug, do not try to handle
+		 * it normally, and panic immediately.
+		 */
+		if (!usermode && (td->td_intr_nesting_level !=3D 0 ||
+		    PCPU_GET(curpcb)->pcb_onfault =3D=3D NULL)) {
+			trap_fatal(frame, eva);
+			return (-1);
+		}
 	}
=20
 	/*
diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c
index 5a8016c..e6d2b5a 100644
--- a/sys/i386/i386/trap.c
+++ b/sys/i386/i386/trap.c
@@ -831,6 +831,11 @@ trap_pfault(frame, usermode, eva)
 			goto nogo;
=20
 		map =3D &vm->vm_map;
+		if (!usermode && (td->td_intr_nesting_level !=3D 0 ||
+		    PCPU_GET(curpcb)->pcb_onfault =3D=3D NULL)) {
+			trap_fatal(frame, eva);
+			return (-1);
+		}
 	}
=20
 	/*
diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c
index 3527ed1..a69b7b8 100644
--- a/sys/kern/subr_trap.c
+++ b/sys/kern/subr_trap.c
@@ -99,6 +99,8 @@ userret(struct thread *td, struct trapframe *frame)
=20
 	CTR3(KTR_SYSC, "userret: thread %p (pid %d, %s)", td, p->p_pid,
             td->td_name);
+	KASSERT((p->p_flag & P_WEXIT) =3D=3D 0,
+	    ("Exiting process returns to usermode"));
 #if 0
 #ifdef DIAGNOSTIC
 	/* Check that we called signotify() enough. */

--MPHowW9WJBu+8Ajw
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (FreeBSD)

iEYEARECAAYFAk5MLlgACgkQC3+MBN1Mb4hyewCgpKYy+yhG+S3bXm5A324n/C8+
6lIAoPRTszmVWdyBQqw5vhJUnpNbhluY
=i6E1
-----END PGP SIGNATURE-----

--MPHowW9WJBu+8Ajw--



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