Allocation requests with __GFP_DMA/__GFP_DMA32 or SLAB_CACHE_DMA/SLAB_CACHE_DMA32 cannot be fulfilled by KFENCE, because they must reside in low memory, whereas KFENCE memory pool is located in high memory.
Skip such allocations to avoid crashes where DMAable memory is expected.
Fixes: 0ce20dd84089 ("mm: add Kernel Electric-Fence infrastructure") Cc: Andrew Morton akpm@linux-foundation.org Cc: Dmitry Vyukov dvyukov@google.com Cc: Marco Elver elver@google.com Cc: Greg Kroah-Hartman gregkh@linuxfoundation.org Cc: stable@vger.kernel.org # 5.12+ Signed-off-by: Alexander Potapenko glider@google.com
---
v2: - added parentheses around the GFP clause, as requested by Marco --- mm/kfence/core.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/mm/kfence/core.c b/mm/kfence/core.c index 4d21ac44d5d35..f7ce3d876bc9e 100644 --- a/mm/kfence/core.c +++ b/mm/kfence/core.c @@ -760,6 +760,14 @@ void *__kfence_alloc(struct kmem_cache *s, size_t size, gfp_t flags) if (size > PAGE_SIZE) return NULL;
+ /* + * Skip DMA allocations. These must reside in the low memory, which we + * cannot guarantee. + */ + if ((flags & (__GFP_DMA | __GFP_DMA32)) || + (s->flags & (SLAB_CACHE_DMA | SLAB_CACHE_DMA32))) + return NULL; + return kfence_guarded_alloc(s, size, flags); }
On Tue, 29 Jun 2021 at 18:17, Alexander Potapenko glider@google.com wrote:
Allocation requests with __GFP_DMA/__GFP_DMA32 or SLAB_CACHE_DMA/SLAB_CACHE_DMA32 cannot be fulfilled by KFENCE, because they must reside in low memory, whereas KFENCE memory pool is located in high memory.
Skip such allocations to avoid crashes where DMAable memory is expected.
Fixes: 0ce20dd84089 ("mm: add Kernel Electric-Fence infrastructure") Cc: Andrew Morton akpm@linux-foundation.org Cc: Dmitry Vyukov dvyukov@google.com Cc: Marco Elver elver@google.com Cc: Greg Kroah-Hartman gregkh@linuxfoundation.org Cc: stable@vger.kernel.org # 5.12+ Signed-off-by: Alexander Potapenko glider@google.com
Reviewed-by: Marco Elver elver@google.com
Thanks!
v2:
- added parentheses around the GFP clause, as requested by Marco
mm/kfence/core.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/mm/kfence/core.c b/mm/kfence/core.c index 4d21ac44d5d35..f7ce3d876bc9e 100644 --- a/mm/kfence/core.c +++ b/mm/kfence/core.c @@ -760,6 +760,14 @@ void *__kfence_alloc(struct kmem_cache *s, size_t size, gfp_t flags) if (size > PAGE_SIZE) return NULL;
/*
* Skip DMA allocations. These must reside in the low memory, which we
* cannot guarantee.
*/
if ((flags & (__GFP_DMA | __GFP_DMA32)) ||
(s->flags & (SLAB_CACHE_DMA | SLAB_CACHE_DMA32)))
return NULL;
return kfence_guarded_alloc(s, size, flags);
}
-- 2.32.0.93.g670b81a890-goog
On Tue, Jun 29, 2021 at 9:47 PM Alexander Potapenko glider@google.com wrote:
Allocation requests with __GFP_DMA/__GFP_DMA32 or SLAB_CACHE_DMA/SLAB_CACHE_DMA32 cannot be fulfilled by KFENCE, because they must reside in low memory, whereas KFENCE memory pool is located in high memory.
Skip such allocations to avoid crashes where DMAable memory is expected.
Fixes: 0ce20dd84089 ("mm: add Kernel Electric-Fence infrastructure") Cc: Andrew Morton akpm@linux-foundation.org Cc: Dmitry Vyukov dvyukov@google.com Cc: Marco Elver elver@google.com Cc: Greg Kroah-Hartman gregkh@linuxfoundation.org Cc: stable@vger.kernel.org # 5.12+ Signed-off-by: Alexander Potapenko glider@google.com
v2:
- added parentheses around the GFP clause, as requested by Marco
mm/kfence/core.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/mm/kfence/core.c b/mm/kfence/core.c index 4d21ac44d5d35..f7ce3d876bc9e 100644 --- a/mm/kfence/core.c +++ b/mm/kfence/core.c @@ -760,6 +760,14 @@ void *__kfence_alloc(struct kmem_cache *s, size_t size, gfp_t flags) if (size > PAGE_SIZE) return NULL;
/*
* Skip DMA allocations. These must reside in the low memory, which we
* cannot guarantee.
*/
if ((flags & (__GFP_DMA | __GFP_DMA32)) ||
(s->flags & (SLAB_CACHE_DMA | SLAB_CACHE_DMA32)))
return NULL;
I prefer to move this check at the top of the function. Although it won't make much difference except avoiding atomic operations in case this condition is true.
return kfence_guarded_alloc(s, size, flags);
}
-- 2.32.0.93.g670b81a890-goog
On Wed, Jun 30, 2021 at 9:02 AM Souptick Joarder jrdr.linux@gmail.com wrote:
On Tue, Jun 29, 2021 at 9:47 PM Alexander Potapenko glider@google.com wrote:
Allocation requests with __GFP_DMA/__GFP_DMA32 or SLAB_CACHE_DMA/SLAB_CACHE_DMA32 cannot be fulfilled by KFENCE, because they must reside in low memory, whereas KFENCE memory pool is located in high memory.
Skip such allocations to avoid crashes where DMAable memory is expected.
Fixes: 0ce20dd84089 ("mm: add Kernel Electric-Fence infrastructure") Cc: Andrew Morton akpm@linux-foundation.org Cc: Dmitry Vyukov dvyukov@google.com Cc: Marco Elver elver@google.com Cc: Greg Kroah-Hartman gregkh@linuxfoundation.org Cc: stable@vger.kernel.org # 5.12+ Signed-off-by: Alexander Potapenko glider@google.com
v2:
- added parentheses around the GFP clause, as requested by Marco
mm/kfence/core.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/mm/kfence/core.c b/mm/kfence/core.c index 4d21ac44d5d35..f7ce3d876bc9e 100644 --- a/mm/kfence/core.c +++ b/mm/kfence/core.c @@ -760,6 +760,14 @@ void *__kfence_alloc(struct kmem_cache *s, size_t size, gfp_t flags) if (size > PAGE_SIZE) return NULL;
/*
* Skip DMA allocations. These must reside in the low memory, which we
* cannot guarantee.
*/
if ((flags & (__GFP_DMA | __GFP_DMA32)) ||
(s->flags & (SLAB_CACHE_DMA | SLAB_CACHE_DMA32)))
return NULL;
I prefer to move this check at the top of the function. Although it won't make much difference except avoiding atomic operations in case this condition is true.
Agreed, we probably shouldn't be expecting a constant flow of allocations from these zones that will be slowed down by this check. On a related note, Marco suggested moving the PAGE_SIZE check to the top of the function as well.
It will also make sense to check for GFP_ZONEMASK instead of just GFP DMA flags. I couldn't see anyone passing e.g. __GFP_HIGHMEM or __GFP_MOVABLE to kmem_cache_alloc(), but according to mm/slab.c it is possible, so just to be on the safe side we'd better ignore them as well.
return kfence_guarded_alloc(s, size, flags);
}
-- 2.32.0.93.g670b81a890-goog
linux-stable-mirror@lists.linaro.org