FAILED: patch "[PATCH] mm, kfence: support kmem_dump_obj() for KFENCE objects" failed to apply to 5.15-stable tree
Subsystems (5)
[email protected]
maintainerThe patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 2dfe63e61cc31ee59ce951672b0850b5229cd5b0 Mon Sep 17 00:00:00 2001
From: Marco Elver <[email protected]>
Date: Thu, 14 Apr 2022 19:13:40 -0700
Subject: [PATCH] mm, kfence: support kmem_dump_obj() for KFENCE objects
Calling kmem_obj_info() via kmem_dump_obj() on KFENCE objects has been producing garbage data due to the object not actually being maintained by SLAB or SLUB.
Fix this by implementing __kfence_obj_info() that copies relevant information to struct kmem_obj_info when the object was allocated by KFENCE; this is called by a common kmem_obj_info(), which also calls the slab/slub/slob specific variant now called __kmem_obj_info().
For completeness, kmem_dump_obj() now displays if the object was allocated by KFENCE.
include/linux/kfence.h +24 -0
@@ -204,6 +204,22 @@ static __always_inline __must_check bool kfence_free(void *addr)*/ bool __must_check kfence_handle_page_fault (unsigned long addr,bool is_write,struct pt_regs *regs); +#ifdef CONFIG_PRINTK +struct kmem_obj_info ; +/** +* __kfence_obj_info() - fill kmem_obj_info struct +* @kpp: kmem_obj_info to be filled +* @object: the object +* +* Return: +* * false - not a KFENCE object +* * true - a KFENCE object, filled @kpp +* +* Copies information to @kpp for KFENCE objects. +*/ +bool __kfence_obj_info (struct kmem_obj_info *kpp,void *object,struct slab *slab); +#endif +#else /* CONFIG_KFENCE */ static inline bool is_kfence_address (const void *addr) {return false; }
@@ -221,6 +237,14 @@ static inline bool __must_check kfence_handle_page_fault(unsigned long addr, booreturn false; } +#ifdef CONFIG_PRINTK +struct kmem_obj_info ; +static inline bool __kfence_obj_info (struct kmem_obj_info *kpp,void *object,struct slab *slab) +{ +return false; +} +#endif +#endif #endif /* _LINUX_KFENCE_H */
mm/kfence/core.c +0 -21
@@ -231,27 +231,6 @@ static bool kfence_unprotect(unsigned long addr)return !KFENCE_WARN_ON (!kfence_protect_page (ALIGN_DOWN (addr,PAGE_SIZE ), false)); } -static inline struct kfence_metadata *addr_to_metadata (unsigned long addr) -{ -long index; - -/* The checks do not affect performance; only called from slow-paths. */ - -if (!is_kfence_address ((void *)addr)) -return NULL ; - -/* -* May be an invalid index if called with an address at the edge of -* __kfence_pool, in which case we would report an "invalid access" -* error. -*/ - index = (addr - (unsigned long )__kfence_pool) / (PAGE_SIZE *2 ) -1 ; -if (index <0 || index >=CONFIG_KFENCE_NUM_OBJECTS ) -return NULL ; - -return &kfence_metadata[index]; -} -static inline unsigned long metadata_to_pageaddr (const struct kfence_metadata *meta) {unsigned long offset = (meta - kfence_metadata +1 ) *PAGE_SIZE *2 ;
mm/kfence/kfence.h +21 -0
@@ -96,6 +96,27 @@ struct kfence_metadata {extern struct kfence_metadata kfence_metadata[CONFIG_KFENCE_NUM_OBJECTS ]; +static inline struct kfence_metadata *addr_to_metadata (unsigned long addr) +{ +long index; + +/* The checks do not affect performance; only called from slow-paths. */ + +if (!is_kfence_address ((void *)addr)) +return NULL ; + +/* +* May be an invalid index if called with an address at the edge of +* __kfence_pool, in which case we would report an "invalid access" +* error. +*/ + index = (addr - (unsigned long )__kfence_pool) / (PAGE_SIZE *2 ) -1 ; +if (index <0 || index >=CONFIG_KFENCE_NUM_OBJECTS ) +return NULL ; + +return &kfence_metadata[index]; +} +/* KFENCE error types for report generation. */ enum kfence_error_type {KFENCE_ERROR_OOB ,/* Detected a out-of-bounds access. */
mm/kfence/report.c +47 -0
50 lines not on this page · raw message
mm/slab.c +1 -1
@@ -3665,7 +3665,7 @@ EXPORT_SYMBOL(__kmalloc_node_track_caller);#endif /* CONFIG_NUMA */ #ifdef CONFIG_PRINTK -void kmem_obj_info (struct kmem_obj_info *kpp,void *object,struct slab *slab) +void __kmem_obj_info (struct kmem_obj_info *kpp,void *object,struct slab *slab) {struct kmem_cache *cachep;unsigned int objnr;
mm/slab.h +1 -1
@@ -868,7 +868,7 @@ struct kmem_obj_info {void *kp_stack[KS_ADDRS_COUNT ]; void *kp_free_stack[KS_ADDRS_COUNT]; }; -void kmem_obj_info (struct kmem_obj_info *kpp,void *object,struct slab *slab); +void __kmem_obj_info (struct kmem_obj_info *kpp,void *object,struct slab *slab);#endif #ifdef CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR
mm/slab_common.c +9 -0
@@ -555,6 +555,13 @@ bool kmem_valid_obj(void *object) }EXPORT_SYMBOL_GPL (kmem_valid_obj); +static void kmem_obj_info (struct kmem_obj_info *kpp,void *object,struct slab *slab) +{ +if (__kfence_obj_info (kpp, object, slab)) +return ; +__kmem_obj_info (kpp, object, slab); +} +/** * kmem_dump_obj - Print available slab provenance information * @object: slab object for which to find provenance information.
@@ -590,6 +597,8 @@ void kmem_dump_obj(void *object)pr_cont (" slab%s %s" , cp, kp.kp_slab_cache->name); else pr_cont(" slab%s", cp); +if (is_kfence_address (object)) +pr_cont (" (kfence)" );if (kp.kp_objp)pr_cont (" start %px" , kp.kp_objp);if (kp.kp_data_offset)
mm/slob.c +1 -1
@@ -463,7 +463,7 @@ static void slob_free(void *block, int size) }#ifdef CONFIG_PRINTK -void kmem_obj_info (struct kmem_obj_info *kpp,void *object,struct slab *slab) +void __kmem_obj_info (struct kmem_obj_info *kpp,void *object,struct slab *slab) { kpp->kp_ptr = object; kpp->kp_slab = slab;
mm/slub.c +1 -1
@@ -4312,7 +4312,7 @@ int __kmem_cache_shutdown(struct kmem_cache *s) }#ifdef CONFIG_PRINTK -void kmem_obj_info (struct kmem_obj_info *kpp,void *object,struct slab *slab) +void __kmem_obj_info (struct kmem_obj_info *kpp,void *object,struct slab *slab) {void *base;int __maybe_unused i;
Marco Elver
maintainerPATCH 1/1 mm, kfence: support kmem_dump_obj() for KFENCE objects
commit 2dfe63e61cc31ee59ce951672b0850b5229cd5b0 upstream.
Calling kmem_obj_info() via kmem_dump_obj() on KFENCE objects has been producing garbage data due to the object not actually being maintained by SLAB or SLUB.
Fix this by implementing __kfence_obj_info() that copies relevant information to struct kmem_obj_info when the object was allocated by KFENCE; this is called by a common kmem_obj_info(), which also calls the slab/slub/slob specific variant now called __kmem_obj_info().
For completeness, kmem_dump_obj() now displays if the object was allocated by KFENCE.
--- include/linux/kfence.h | 24 +++++++++++++++++++++ mm/kfence/core.c | 21 ------------------- mm/kfence/kfence.h | 21 +++++++++++++++++++ mm/kfence/report.c | 47 ++++++++++++++++++++++++++++++++++++++++++ mm/slab.c | 2 +- mm/slab.h | 2 +- mm/slab_common.c | 9 ++++++++ mm/slob.c | 2 +- mm/slub.c | 2 +- 9 files changed, 105 insertions(+), 25 deletions(-)
include/linux/kfence.h +24 -0
@@ -202,6 +202,22 @@ static __always_inline __must_check bool kfence_free(void *addr)*/ bool __must_check kfence_handle_page_fault (unsigned long addr,bool is_write,struct pt_regs *regs); +#ifdef CONFIG_PRINTK +struct kmem_obj_info ; +/** +* __kfence_obj_info() - fill kmem_obj_info struct +* @kpp: kmem_obj_info to be filled +* @object: the object +* +* Return: +* * false - not a KFENCE object +* * true - a KFENCE object, filled @kpp +* +* Copies information to @kpp for KFENCE objects. +*/ +bool __kfence_obj_info (struct kmem_obj_info *kpp,void *object,struct page *page); +#endif +#else /* CONFIG_KFENCE */ static inline bool is_kfence_address (const void *addr) {return false; }
@@ -219,6 +235,14 @@ static inline bool __must_check kfence_handle_page_fault(unsigned long addr, booreturn false; } +#ifdef CONFIG_PRINTK +struct kmem_obj_info ; +static inline bool __kfence_obj_info (struct kmem_obj_info *kpp,void *object,struct page *page) +{ +return false; +} +#endif +#endif #endif /* _LINUX_KFENCE_H */
mm/kfence/core.c +0 -21
@@ -221,27 +221,6 @@ static bool kfence_unprotect(unsigned long addr)return !KFENCE_WARN_ON (!kfence_protect_page (ALIGN_DOWN (addr,PAGE_SIZE ), false)); } -static inline struct kfence_metadata *addr_to_metadata (unsigned long addr) -{ -long index; - -/* The checks do not affect performance; only called from slow-paths. */ - -if (!is_kfence_address ((void *)addr)) -return NULL ; - -/* -* May be an invalid index if called with an address at the edge of -* __kfence_pool, in which case we would report an "invalid access" -* error. -*/ - index = (addr - (unsigned long )__kfence_pool) / (PAGE_SIZE *2 ) -1 ; -if (index <0 || index >=CONFIG_KFENCE_NUM_OBJECTS ) -return NULL ; - -return &kfence_metadata[index]; -} -static inline unsigned long metadata_to_pageaddr (const struct kfence_metadata *meta) {unsigned long offset = (meta - kfence_metadata +1 ) *PAGE_SIZE *2 ;
mm/kfence/kfence.h +21 -0
@@ -93,6 +93,27 @@ struct kfence_metadata {extern struct kfence_metadata kfence_metadata[CONFIG_KFENCE_NUM_OBJECTS ]; +static inline struct kfence_metadata *addr_to_metadata (unsigned long addr) +{ +long index; + +/* The checks do not affect performance; only called from slow-paths. */ + +if (!is_kfence_address ((void *)addr)) +return NULL ; + +/* +* May be an invalid index if called with an address at the edge of +* __kfence_pool, in which case we would report an "invalid access" +* error. +*/ + index = (addr - (unsigned long )__kfence_pool) / (PAGE_SIZE *2 ) -1 ; +if (index <0 || index >=CONFIG_KFENCE_NUM_OBJECTS ) +return NULL ; + +return &kfence_metadata[index]; +} +/* KFENCE error types for report generation. */ enum kfence_error_type {KFENCE_ERROR_OOB ,/* Detected a out-of-bounds access. */
mm/kfence/report.c +47 -0
50 lines not on this page · raw message
mm/slab.c +1 -1
@@ -3658,7 +3658,7 @@ EXPORT_SYMBOL(__kmalloc_node_track_caller);#endif /* CONFIG_NUMA */ #ifdef CONFIG_PRINTK -void kmem_obj_info (struct kmem_obj_info *kpp,void *object,struct page *page) +void __kmem_obj_info (struct kmem_obj_info *kpp,void *object,struct page *page) {struct kmem_cache *cachep;unsigned int objnr;
mm/slab.h +1 -1
@@ -643,7 +643,7 @@ struct kmem_obj_info {void *kp_stack[KS_ADDRS_COUNT ];void *kp_free_stack[KS_ADDRS_COUNT ]; }; -void kmem_obj_info (struct kmem_obj_info *kpp,void *object,struct page *page); +void __kmem_obj_info (struct kmem_obj_info *kpp,void *object,struct page *page);#endif #endif /* MM_SLAB_H */
mm/slab_common.c +9 -0
@@ -568,6 +568,13 @@ bool kmem_valid_obj(void *object) }EXPORT_SYMBOL_GPL (kmem_valid_obj); +static void kmem_obj_info (struct kmem_obj_info *kpp,void *object,struct page *page) +{ +if (__kfence_obj_info (kpp, object, page)) +return ; +__kmem_obj_info (kpp, object, page); +} +/** * kmem_dump_obj - Print available slab provenance information * @object: slab object for which to find provenance information.
@@ -603,6 +610,8 @@ void kmem_dump_obj(void *object)pr_cont (" slab%s %s" , cp, kp.kp_slab_cache->name); else pr_cont(" slab%s", cp); +if (is_kfence_address (object)) +pr_cont (" (kfence)" );if (kp.kp_objp)pr_cont (" start %px" , kp.kp_objp);if (kp.kp_data_offset)
mm/slob.c +1 -1
@@ -462,7 +462,7 @@ static void slob_free(void *block, int size) }#ifdef CONFIG_PRINTK -void kmem_obj_info (struct kmem_obj_info *kpp,void *object,struct page *page) +void __kmem_obj_info (struct kmem_obj_info *kpp,void *object,struct page *page) { kpp->kp_ptr = object; kpp->kp_page = page;
mm/slub.c +1 -1
@@ -4299,7 +4299,7 @@ int __kmem_cache_shutdown(struct kmem_cache *s) }#ifdef CONFIG_PRINTK -void kmem_obj_info (struct kmem_obj_info *kpp,void *object,struct page *page) +void __kmem_obj_info (struct kmem_obj_info *kpp,void *object,struct page *page) {void *base;int __maybe_unused i;
Signature · 1 line
2.36.0.rc0.470.gd361397f0d-goog
Greg KH
maintainerRe: [PATCH 5.15.y] mm, kfence: support kmem_dump_obj() for KFENCE objects
Quoted 26 lines · Marco Elver
commit
2dfe63e61cc31ee59ce951672b0850b5229cd5b0upstream.Calling
kmem_obj_info()viakmem_dump_obj()on KFENCE objects has been producing garbage data due to the object not actually being maintained by SLAB or SLUB.Fix this by implementing
__kfence_obj_info()that copies relevant information to structkmem_obj_infowhen the object was allocated by KFENCE; this is called by a commonkmem_obj_info(), which also calls the slab/slub/slob specific variant now called__kmem_obj_info().For completeness,
kmem_dump_obj()now displays if the object was allocated by KFENCE.Fixes b89fb5ef0ce6 ("mm, kfence: insert KFENCE hooks for SLUB")Fixes d3fb45f370d9 ("mm, kfence: insert KFENCE hooks for SLAB")Signed-off-by Marco Elver <[email protected]>Reviewed-by Hyeonggon Yoo <[email protected]>Reported-by kernel test robot <[email protected]>Signed-off-by Andrew Morton <[email protected]>Signed-off-by Linus Torvalds <[email protected]>[[email protected]: backport - substitute uses of struct slab with page]Signed-off-by Marco Elver <[email protected]>
Quoted 11 lines
--- include/linux/kfence.h | 24 +++++++++++++++++++++ mm/kfence/core.c | 21 ------------------- mm/kfence/kfence.h | 21 +++++++++++++++++++ mm/kfence/report.c | 47 ++++++++++++++++++++++++++++++++++++++++++ mm/slab.c | 2 +- mm/slab.h | 2 +- mm/slab_common.c | 9 ++++++++ mm/slob.c | 2 +- mm/slub.c | 2 +- 9 files changed, 105 insertions(+), 25 deletions(-)
Now queued up, thanks.
greg k-h