Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/x86/x86 Ah, finally found you. Fix two bugs in pmap...



details:   https://anonhg.NetBSD.org/src/rev/f59c1a1cba0f
branches:  trunk
changeset: 828771:f59c1a1cba0f
user:      maxv <maxv%NetBSD.org@localhost>
date:      Sun Dec 31 15:41:05 2017 +0000

description:
Ah, finally found you. Fix two bugs in pmap_remap_largepages(), that
could cause KASLR kernels to crash early during the boot procedure.

pmap_remap_largepages assumes that the kernel is far from the end of
the VM space, but this assumption does not hold with KASLR, since the
kernel sections are allowed to reside in the very last page of the VM
space.

Doing +NBPD_L2 or roundup() in such cases caused an integer overflow,
which caused a page fault when touching &L2_BASE, which in turn caused
an immediate CPU reset and a reboot.

Took me a while to reproduce and debug this issue.

diffstat:

 sys/arch/x86/x86/pmap.c |  25 +++++++++++++++++--------
 1 files changed, 17 insertions(+), 8 deletions(-)

diffs (66 lines):

diff -r f481ab1831c2 -r f59c1a1cba0f sys/arch/x86/x86/pmap.c
--- a/sys/arch/x86/x86/pmap.c   Sun Dec 31 11:43:42 2017 +0000
+++ b/sys/arch/x86/x86/pmap.c   Sun Dec 31 15:41:05 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pmap.c,v 1.270 2017/12/28 14:34:39 maxv Exp $  */
+/*     $NetBSD: pmap.c,v 1.271 2017/12/31 15:41:05 maxv Exp $  */
 
 /*
  * Copyright (c) 2008, 2010, 2016, 2017 The NetBSD Foundation, Inc.
@@ -170,7 +170,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.270 2017/12/28 14:34:39 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.271 2017/12/31 15:41:05 maxv Exp $");
 
 #include "opt_user_ldt.h"
 #include "opt_lockdebug.h"
@@ -1601,10 +1601,13 @@
                        continue;
                }
                kva = roundup(bootspace.segs[i].va, NBPD_L2);
+               if (kva < bootspace.segs[i].va) {
+                       continue;
+               }
                kva_end = rounddown(bootspace.segs[i].va +
-                       bootspace.segs[i].sz, NBPD_L1);
+                       bootspace.segs[i].sz, NBPD_L2);
                pa = roundup(bootspace.segs[i].pa, NBPD_L2);
-               for (/* */; kva + NBPD_L2 <= kva_end; kva += NBPD_L2, pa += NBPD_L2) {
+               for (/* */; kva < kva_end; kva += NBPD_L2, pa += NBPD_L2) {
                        pde = &L2_BASE[pl2_i(kva)];
                        *pde = pa | pmap_pg_g | PG_PS | PG_KR | PG_V;
                        tlbflushg();
@@ -1617,10 +1620,13 @@
                        continue;
                }
                kva = roundup(bootspace.segs[i].va, NBPD_L2);
+               if (kva < bootspace.segs[i].va) {
+                       continue;
+               }
                kva_end = rounddown(bootspace.segs[i].va +
-                       bootspace.segs[i].sz, NBPD_L1);
+                       bootspace.segs[i].sz, NBPD_L2);
                pa = roundup(bootspace.segs[i].pa, NBPD_L2);
-               for (/* */; kva + NBPD_L2 <= kva_end; kva += NBPD_L2, pa += NBPD_L2) {
+               for (/* */; kva < kva_end; kva += NBPD_L2, pa += NBPD_L2) {
                        pde = &L2_BASE[pl2_i(kva)];
                        *pde = pa | pmap_pg_g | PG_PS | pmap_pg_nx | PG_KR | PG_V;
                        tlbflushg();
@@ -1633,10 +1639,13 @@
                        continue;
                }
                kva = roundup(bootspace.segs[i].va, NBPD_L2);
+               if (kva < bootspace.segs[i].va) {
+                       continue;
+               }
                kva_end = rounddown(bootspace.segs[i].va +
-                       bootspace.segs[i].sz, NBPD_L1);
+                       bootspace.segs[i].sz, NBPD_L2);
                pa = roundup(bootspace.segs[i].pa, NBPD_L2);
-               for (/* */; kva + NBPD_L2 <= kva_end; kva += NBPD_L2, pa += NBPD_L2) {
+               for (/* */; kva < kva_end; kva += NBPD_L2, pa += NBPD_L2) {
                        pde = &L2_BASE[pl2_i(kva)];
                        *pde = pa | pmap_pg_g | PG_PS | pmap_pg_nx | PG_KW | PG_V;
                        tlbflushg();



Home | Main Index | Thread Index | Old Index