mm/cma.c: fail if fixed declaration can’t be honored [Linux 4.9.188]

This Linux kernel change "mm/cma.c: fail if fixed declaration can’t be honored" is included in the Linux 4.9.188 release. This change is authored by Doug Berger <opendmb [at]> on Tue Jul 16 16:26:24 2019 -0700. The commit for this change in Linux stable tree is ad20411 (patch) which is from upstream commit c633324. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream c633324.

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.

Fixes: 5ea3b1b2f8ad ("cma: add placement specifier for "cma=" kernel parameter")
Signed-off-by: Doug Berger <>
Acked-by: Michal Nazarewicz <>
Cc: Yue Hu <>
Cc: Mike Rapoport <>
Cc: Laura Abbott <>
Cc: Peng Fan <>
Cc: Thomas Gleixner <>
Cc: Marek Szyprowski <>
Cc: Andrey Konovalov <>
Signed-off-by: Andrew Morton <>
Signed-off-by: Linus Torvalds <>
Signed-off-by: Sasha Levin <>

There are 13 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 mm/cma.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/mm/cma.c b/mm/cma.c
index 4ea0f32..7cb569a 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) ||

Leave a Reply

Your email address will not be published. Required fields are marked *