Subject: port-powerpc/29507: pmap_extract() dereferencing NULL pointer
To: None <port-powerpc-maintainer@netbsd.org, gnats-admin@netbsd.org,>
From: None <nludban@terabeam.com>
List: netbsd-bugs
Date: 02/22/2005 20:28:00
>Number: 29507
>Category: port-powerpc
>Synopsis: pmap_extract() dereferencing NULL pointer
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: port-powerpc-maintainer
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Tue Feb 22 20:28:00 +0000 2005
>Originator: Neil Ludban
>Release: 2.99.15
>Organization:
>Environment:
powerpc (private port to MPC8272)
>Description:
In uvm_fault(), a NULL pointer is passed to pmap_extract():
/*
* dont play with VAs that are already mapped
* except for center)
*/
if (lcv != centeridx &&
pmap_extract(ufi.orig_map->pmap, currva, NULL)) {
pages[lcv] = PGO_DONTCARE;
continue;
}
The implementation in arch/powerpc/oea/pmap.c uses this value
without checking if it's NULL.
>How-To-Repeat:
>Fix:
(Patch against $NetBSD: pmap.c,v 1.27 2005/01/16 23:52:12 chs Exp $)
Index: arch/powerpc/oea/pmap.c
===================================================================
RCS file: /usr/cvsroot/src/sys/arch/powerpc/oea/pmap.c,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 pmap.c
--- arch/powerpc/oea/pmap.c 2005/02/10 19:21:21 1.1.1.2
+++ arch/powerpc/oea/pmap.c 2005/02/22 19:56:49
@@ -2030,7 +2030,8 @@
battable[va >> ADDR_SR_SHFT].batl;
register_t mask =
(~(batu & BAT_BL) << 15) & ~0x1ffffL;
- *pap = (batl & mask) | (va & ~mask);
+ if (pap != NULL)
+ *pap = (batl & mask) | (va & ~mask);
return TRUE;
}
} else {
@@ -2041,11 +2042,13 @@
BAT601_VA_MATCH_P(batu, batl, va)) {
register_t mask =
(~(batl & BAT601_BSM) << 17) & ~0x1ffffL;
- *pap = (batl & mask) | (va & ~mask);
+ if (pap != NULL)
+ *pap = (batl & mask) | (va & ~mask);
return TRUE;
} else if (SR601_VALID_P(sr) &&
SR601_PA_MATCH_P(sr, va)) {
- *pap = va;
+ if (pap != NULL)
+ *pap = va;
return TRUE;
}
}
@@ -2056,7 +2059,9 @@
pvo = pmap_pvo_find_va(pm, va & ~ADDR_POFF, NULL);
if (pvo != NULL) {
PMAP_PVO_CHECK(pvo); /* sanity check */
- *pap = (pvo->pvo_pte.pte_lo & PTE_RPGN) | (va & ADDR_POFF);
+ if (pap != NULL)
+ *pap = ((pvo->pvo_pte.pte_lo & PTE_RPGN)
+ | (va & ADDR_POFF));
}
pmap_interrupts_restore(msr);
return pvo != NULL;