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/b1d73d5e4697
branches:  trunk
changeset: 358470:b1d73d5e4697
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 5ba3396be3e5 -r b1d73d5e4697 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