From 12dac6c097c2eefb15a289b9fed2e14eb80b57b3 Mon Sep 17 00:00:00 2001 From: Aaron Durbin Date: Fri, 12 May 2017 09:55:16 -0500 Subject: [PATCH] UPSTREAM: util/cbmem: mmap underflow on low addresses There is code to adjust the mapping down if a mmap fails at a physical address. However, if the address is less than the page size of the system then the physical offset will underflow. This can actually cause a kernel panic on when operating on /dev/mem. The failing condition happens when the requested mapping at 0 fails in the kernel. The fallback path is taken and page size is subtracted from 0 making a very large offset. The PAT code in the kernel fails with a BUG_ON in reserve_memtype() checking start >= end. The kernel needs to be fixed as well, but this fallback path is wrong as well. BUG=b:38211793 Change-Id: Idd5b22027633e5e1febd140336244f25a5304de4 Signed-off-by: Patrick Georgi Original-Commit-Id: 7ad44eed08b9811d97462b3c990129187f77e2ca Original-Change-Id: I32b0c15b2f1aa43fc57656d5d2d5f0e4e90e94ef Original-Signed-off-by: Aaron Durbin Original-Reviewed-on: https://review.coreboot.org/19679 Original-Tested-by: build bot (Jenkins) Original-Reviewed-by: Patrick Georgi Original-Reviewed-by: Philippe Mathieu-Daud Original-Reviewed-by: Julius Werner Original-Reviewed-by: Furquan Shaikh Original-Reviewed-by: Paul Menzel Reviewed-on: https://chromium-review.googlesource.com/506197 Commit-Ready: Patrick Georgi Tested-by: Patrick Georgi Reviewed-by: Patrick Georgi --- util/cbmem/cbmem.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/util/cbmem/cbmem.c b/util/cbmem/cbmem.c index c1b1caa572..48a1bc963d 100644 --- a/util/cbmem/cbmem.c +++ b/util/cbmem/cbmem.c @@ -165,7 +165,9 @@ static void *map_memory_size(u64 physical, size_t size, uint8_t abort_on_failure v = mmap(NULL, size, PROT_READ, MAP_SHARED, mem_fd, p); - if (v == MAP_FAILED) { + /* Only try growing down when address exceeds page size so that + one doesn't underflow the offset request. */ + if (v == MAP_FAILED && p >= page) { /* The mapped area may have overrun the upper cbmem boundary when trying to * align to the page size. Try growing down instead of up... */