| From 0c517af8261c2813564fd8d79821244ccfbbea96 Mon Sep 17 00:00:00 2001 |
| From: Doug Berger <opendmb@gmail.com> |
| Date: Tue, 16 Jul 2019 16:26:24 -0700 |
| Subject: mm/cma.c: fail if fixed declaration can't be honored |
| |
| [ Upstream commit c633324e311243586675e732249339685e5d6faa ] |
| |
| The description of cma_declare_contiguous() indicates that if the |
| 'fixed' argument is true the reserved contiguous area must be exactly at |
| the address of the 'base' argument. |
| |
| However, the function currently allows the 'base', 'size', and 'limit' |
| arguments to be silently adjusted to meet alignment constraints. This |
| commit enforces the documented behavior through explicit checks that |
| return an error if the region does not fit within a specified region. |
| |
| Link: http://lkml.kernel.org/r/1561422051-16142-1-git-send-email-opendmb@gmail.com |
| Fixes: 5ea3b1b2f8ad ("cma: add placement specifier for "cma=" kernel parameter") |
| Signed-off-by: Doug Berger <opendmb@gmail.com> |
| Acked-by: Michal Nazarewicz <mina86@mina86.com> |
| Cc: Yue Hu <huyue2@yulong.com> |
| Cc: Mike Rapoport <rppt@linux.ibm.com> |
| Cc: Laura Abbott <labbott@redhat.com> |
| Cc: Peng Fan <peng.fan@nxp.com> |
| Cc: Thomas Gleixner <tglx@linutronix.de> |
| Cc: Marek Szyprowski <m.szyprowski@samsung.com> |
| Cc: Andrey Konovalov <andreyknvl@google.com> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| mm/cma.c | 13 +++++++++++++ |
| 1 file changed, 13 insertions(+) |
| |
| diff --git a/mm/cma.c b/mm/cma.c |
| index 4ea0f32761c1a..7cb569a188c48 100644 |
| --- a/mm/cma.c |
| +++ b/mm/cma.c |
| @@ -268,6 +268,12 @@ int __init cma_declare_contiguous(phys_addr_t base, |
| */ |
| alignment = max(alignment, (phys_addr_t)PAGE_SIZE << |
| max_t(unsigned long, MAX_ORDER - 1, pageblock_order)); |
| + if (fixed && base & (alignment - 1)) { |
| + ret = -EINVAL; |
| + pr_err("Region at %pa must be aligned to %pa bytes\n", |
| + &base, &alignment); |
| + goto err; |
| + } |
| base = ALIGN(base, alignment); |
| size = ALIGN(size, alignment); |
| limit &= ~(alignment - 1); |
| @@ -298,6 +304,13 @@ int __init cma_declare_contiguous(phys_addr_t base, |
| if (limit == 0 || limit > memblock_end) |
| limit = memblock_end; |
| |
| + if (base + size > limit) { |
| + ret = -EINVAL; |
| + pr_err("Size (%pa) of region at %pa exceeds limit (%pa)\n", |
| + &size, &base, &limit); |
| + goto err; |
| + } |
| + |
| /* Reserve memory */ |
| if (fixed) { |
| if (memblock_is_region_reserved(base, size) || |
| -- |
| 2.20.1 |
| |