untrusted comment: signature from openbsd 5.9 base secret key
RWQJVNompF3pwYa4tzI4bSrxrywOVRNvU/IRnMfm6wb0LNoTFJeyeZOe45Rj6x7kOPs4jMtFRuCzaT4wPqDKUSXPaDbrEv2tqAM=
OpenBSD 5.9 errata 20, Jul 14, 2016:
Unchecked parameters and integer overflows in the amap allocation routines
could cause malloc(9) to either not allocate enough memory, leading to memory
corruption, or to trigger a "malloc: allocation too large" panic.
Apply by doing:
signify -Vep /etc/signify/openbsd-59-base.pub -x 020_amap.patch.sig \
-m - | (cd /usr/src && patch -p0)
And then rebuild and install a kernel:
cd /usr/src/sys/arch/`machine`/conf
KK=`sysctl -n kern.osversion | cut -d# -f1`
config $KK
cd ../compile/$KK
make
make install
Index: sys/arch/amd64/amd64/vmm.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/amd64/vmm.c,v
retrieving revision 1.38
diff -u -p -r1.38 vmm.c
--- sys/arch/amd64/amd64/vmm.c 23 Feb 2016 17:17:31 -0000 1.38
+++ sys/arch/amd64/amd64/vmm.c 14 Jul 2016 15:21:07 -0000
@@ -1016,7 +1016,7 @@ vm_impl_init_vmx(struct vm *vm)
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_INHERIT_NONE,
MADV_NORMAL,
- UVM_FLAG_FIXED | UVM_FLAG_OVERLAY));
+ UVM_FLAG_FIXED));
if (ret) {
printf("vm_impl_init_vmx: uvm_mapanon failed (%d)\n", ret);
/* uvm_map_deallocate calls pmap_destroy for us */
Index: sys/uvm/uvm_amap.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_amap.c,v
retrieving revision 1.59
diff -u -p -r1.59 uvm_amap.c
--- sys/uvm/uvm_amap.c 21 Aug 2015 16:04:35 -0000 1.59
+++ sys/uvm/uvm_amap.c 14 Jul 2016 15:21:09 -0000
@@ -35,6 +35,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/stdint.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/pool.h>
@@ -165,15 +166,29 @@ static inline struct vm_amap *
amap_alloc1(int slots, int padslots, int waitf)
{
struct vm_amap *amap;
- int totalslots;
+ size_t totalslots = (size_t)slots + padslots;
amap = pool_get(&uvm_amap_pool, (waitf == M_WAITOK) ? PR_WAITOK
: PR_NOWAIT);
if (amap == NULL)
return(NULL);
- totalslots = malloc_roundup((slots + padslots) * MALLOC_SLOT_UNIT) /
+ /*
+ * Make sure that totalslots * MALLOC_SLOT_UNIT is within
+ * a size_t, AND: since malloc_roundup may round its argument
+ * to a multiple of the PAGE_SIZE, make sure that malloc_roundup
+ * cannot wrap totalslots * MALLOC_SLOT_UNIT to zero.
+ */
+ if (totalslots >= (trunc_page(SIZE_MAX) / MALLOC_SLOT_UNIT))
+ return (NULL);
+
+ totalslots = malloc_roundup(totalslots * MALLOC_SLOT_UNIT) /
MALLOC_SLOT_UNIT;
+ if (totalslots > INT_MAX)
+ return (NULL);
+
+ KASSERT(totalslots > 0);
+
amap->am_ref = 1;
amap->am_flags = 0;
#ifdef UVM_AMAP_PPREF
@@ -183,7 +198,7 @@ amap_alloc1(int slots, int padslots, int
amap->am_nslot = slots;
amap->am_nused = 0;
- amap->am_slots = malloc(totalslots * MALLOC_SLOT_UNIT, M_UVMAMAP,
+ amap->am_slots = mallocarray(totalslots, MALLOC_SLOT_UNIT, M_UVMAMAP,
waitf);
if (amap->am_slots == NULL)
goto fail1;
@@ -210,10 +225,14 @@ struct vm_amap *
amap_alloc(vaddr_t sz, vaddr_t padsz, int waitf)
{
struct vm_amap *amap;
- int slots, padslots;
+ size_t slots, padslots;
AMAP_B2SLOT(slots, sz); /* load slots */
AMAP_B2SLOT(padslots, padsz);
+
+ /* Ensure that slots + padslots <= INT_MAX */
+ if (slots > INT_MAX || padslots > INT_MAX - slots)
+ return (NULL);
amap = amap_alloc1(slots, padslots, waitf);
if (amap) {