Message ID | 1675750519-1064-1-git-send-email-quic_zhenhuah@quicinc.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | mm: kfence: export kfence_enabled as global variables | expand |
On Tue, 7 Feb 2023 at 07:15, Zhenhua Huang <quic_zhenhuah@quicinc.com> wrote: > > Export the variable to ease the judgement of whether kfence enabled > at runtime. It should be more precise than through kernel config > "CONFIG_KFENCE". > > For example We can disable kfence at runtime using bootargs > "kfence.sample_interval=0" but CONFIG_KFENCE enabled. > It was false positive. > > Signed-off-by: Zhenhua Huang <quic_zhenhuah@quicinc.com> > --- > arch/arm64/mm/pageattr.c | 3 ++- > include/linux/kfence.h | 2 ++ > mm/kfence/core.c | 2 +- > 3 files changed, 5 insertions(+), 2 deletions(-) > > diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c > index 79dd201..208d780 100644 > --- a/arch/arm64/mm/pageattr.c > +++ b/arch/arm64/mm/pageattr.c > @@ -7,6 +7,7 @@ > #include <linux/module.h> > #include <linux/sched.h> > #include <linux/vmalloc.h> > +#include <linux/kfence.h> > > #include <asm/cacheflush.h> > #include <asm/set_memory.h> > @@ -27,7 +28,7 @@ bool can_set_direct_map(void) > * protect/unprotect single pages. > */ > return (rodata_enabled && rodata_full) || debug_pagealloc_enabled() || > - IS_ENABLED(CONFIG_KFENCE); > + kfence_enabled; Unfortunately this won't work, because it's possible to enable KFENCE after the kernel has booted with e.g.: echo 100 > /sys/module/kfence/parameters/sample_interval What is the problem you have encountered? Is the page-granular direct map causing issues?
Thanks Marco! On 2023/2/7 15:19, Marco Elver wrote: > On Tue, 7 Feb 2023 at 07:15, Zhenhua Huang <quic_zhenhuah@quicinc.com> wrote: >> >> Export the variable to ease the judgement of whether kfence enabled >> at runtime. It should be more precise than through kernel config >> "CONFIG_KFENCE". >> >> For example We can disable kfence at runtime using bootargs >> "kfence.sample_interval=0" but CONFIG_KFENCE enabled. >> It was false positive. >> >> Signed-off-by: Zhenhua Huang <quic_zhenhuah@quicinc.com> >> --- >> arch/arm64/mm/pageattr.c | 3 ++- >> include/linux/kfence.h | 2 ++ >> mm/kfence/core.c | 2 +- >> 3 files changed, 5 insertions(+), 2 deletions(-) >> >> diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c >> index 79dd201..208d780 100644 >> --- a/arch/arm64/mm/pageattr.c >> +++ b/arch/arm64/mm/pageattr.c >> @@ -7,6 +7,7 @@ >> #include <linux/module.h> >> #include <linux/sched.h> >> #include <linux/vmalloc.h> >> +#include <linux/kfence.h> >> >> #include <asm/cacheflush.h> >> #include <asm/set_memory.h> >> @@ -27,7 +28,7 @@ bool can_set_direct_map(void) >> * protect/unprotect single pages. >> */ >> return (rodata_enabled && rodata_full) || debug_pagealloc_enabled() || >> - IS_ENABLED(CONFIG_KFENCE); >> + kfence_enabled; > > Unfortunately this won't work, because it's possible to enable KFENCE > after the kernel has booted with e.g.: echo 100 > > /sys/module/kfence/parameters/sample_interval Yeah, got it. Thanks for catching it. > > What is the problem you have encountered? Is the page-granular direct > map causing issues? We're working on a low memory target, page-granular mapping costed more (2M per 1GB) memory. Due to GKI constraints, it is not easy to disable CONFIG_KFENCE. So my intention was to move the judgement to runtime configurable w/ CONFIG_KFENCE on... Do you have any further suggestion/proposal on this? Many Thanks! Thanks, Zhenhua
> > > > What is the problem you have encountered? Is the page-granular direct > > map causing issues? > We're working on a low memory target, page-granular mapping costed more > (2M per 1GB) memory. Due to GKI constraints, it is not easy to disable > CONFIG_KFENCE. So my intention was to move the judgement to runtime > configurable w/ CONFIG_KFENCE on... > > Do you have any further suggestion/proposal on this? Many Thanks! Right now CONFIG_KFENCE allocates 512Kb for the GKI kernel (only 63 objects instead of the default 255): https://cs.android.com/android/kernel/superproject/+/common-android-mainline:common/arch/arm64/configs/gki_defconfig;l=686?q=CONFIG_KFENCE_NUM_OBJECTS Where do 2M come from?
On 2023/2/7 18:28, Alexander Potapenko wrote: >>> >>> What is the problem you have encountered? Is the page-granular direct >>> map causing issues? >> We're working on a low memory target, page-granular mapping costed more >> (2M per 1GB) memory. Due to GKI constraints, it is not easy to disable >> CONFIG_KFENCE. So my intention was to move the judgement to runtime >> configurable w/ CONFIG_KFENCE on... >> >> Do you have any further suggestion/proposal on this? Many Thanks! > > Right now CONFIG_KFENCE allocates 512Kb for the GKI kernel (only 63 > objects instead of the default 255): > https://cs.android.com/android/kernel/superproject/+/common-android-mainline:common/arch/arm64/configs/gki_defconfig;l=686?q=CONFIG_KFENCE_NUM_OBJECTS > Where do 2M come from? Hi Alexander, It is not from KFENCE cost itself, but from the requirement it needs page-granular mapping. 2M per 1GB cost is from linear mapping for page granularity. You can see can_set_direct_map() is used for whether allowing section mapping or not.
On Tue, Feb 07, 2023 at 03:46:53PM +0800, Zhenhua Huang wrote: > Thanks Marco! > > On 2023/2/7 15:19, Marco Elver wrote: > > On Tue, 7 Feb 2023 at 07:15, Zhenhua Huang <quic_zhenhuah@quicinc.com> wrote: > > > > > > Export the variable to ease the judgement of whether kfence enabled > > > at runtime. It should be more precise than through kernel config > > > "CONFIG_KFENCE". > > > > > > For example We can disable kfence at runtime using bootargs > > > "kfence.sample_interval=0" but CONFIG_KFENCE enabled. > > > It was false positive. > > > > > > Signed-off-by: Zhenhua Huang <quic_zhenhuah@quicinc.com> > > > --- > > > arch/arm64/mm/pageattr.c | 3 ++- > > > include/linux/kfence.h | 2 ++ > > > mm/kfence/core.c | 2 +- > > > 3 files changed, 5 insertions(+), 2 deletions(-) > > > > > > diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c > > > index 79dd201..208d780 100644 > > > --- a/arch/arm64/mm/pageattr.c > > > +++ b/arch/arm64/mm/pageattr.c > > > @@ -7,6 +7,7 @@ > > > #include <linux/module.h> > > > #include <linux/sched.h> > > > #include <linux/vmalloc.h> > > > +#include <linux/kfence.h> > > > > > > #include <asm/cacheflush.h> > > > #include <asm/set_memory.h> > > > @@ -27,7 +28,7 @@ bool can_set_direct_map(void) > > > * protect/unprotect single pages. > > > */ > > > return (rodata_enabled && rodata_full) || debug_pagealloc_enabled() || > > > - IS_ENABLED(CONFIG_KFENCE); > > > + kfence_enabled; > > > > Unfortunately this won't work, because it's possible to enable KFENCE > > after the kernel has booted with e.g.: echo 100 > > > /sys/module/kfence/parameters/sample_interval > Yeah, got it. Thanks for catching it. > > > > What is the problem you have encountered? Is the page-granular direct > > map causing issues? > We're working on a low memory target, page-granular mapping costed more (2M > per 1GB) memory. Due to GKI constraints, it is not easy to disable > CONFIG_KFENCE. So my intention was to move the judgement to runtime > configurable w/ CONFIG_KFENCE on... > > Do you have any further suggestion/proposal on this? Many Thanks! Just to check, the cost is because we're mapping *all* of memory at page granulatrity, right? If we were to just map the KFENCE region a page granularity, would that be a sufficient saving? We didn't do that so far because it was simpler to just map everything at page granularity (and that's also required by rodata_full, which I though android used?). If it's really important (and rodata_full isn't being used), we could try to do that. To do that we'd need to choose the KFENCE region *before* arm64 creates the fine-grain translation tables, which probable needs an arch_ hook. Thanks, Mark.
Thanks Mark! On 2023/2/7 18:48, Mark Rutland wrote: > On Tue, Feb 07, 2023 at 03:46:53PM +0800, Zhenhua Huang wrote: >> Thanks Marco! >> >> On 2023/2/7 15:19, Marco Elver wrote: >>> On Tue, 7 Feb 2023 at 07:15, Zhenhua Huang <quic_zhenhuah@quicinc.com> wrote: >>>> >>>> Export the variable to ease the judgement of whether kfence enabled >>>> at runtime. It should be more precise than through kernel config >>>> "CONFIG_KFENCE". >>>> >>>> For example We can disable kfence at runtime using bootargs >>>> "kfence.sample_interval=0" but CONFIG_KFENCE enabled. >>>> It was false positive. >>>> >>>> Signed-off-by: Zhenhua Huang <quic_zhenhuah@quicinc.com> >>>> --- >>>> arch/arm64/mm/pageattr.c | 3 ++- >>>> include/linux/kfence.h | 2 ++ >>>> mm/kfence/core.c | 2 +- >>>> 3 files changed, 5 insertions(+), 2 deletions(-) >>>> >>>> diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c >>>> index 79dd201..208d780 100644 >>>> --- a/arch/arm64/mm/pageattr.c >>>> +++ b/arch/arm64/mm/pageattr.c >>>> @@ -7,6 +7,7 @@ >>>> #include <linux/module.h> >>>> #include <linux/sched.h> >>>> #include <linux/vmalloc.h> >>>> +#include <linux/kfence.h> >>>> >>>> #include <asm/cacheflush.h> >>>> #include <asm/set_memory.h> >>>> @@ -27,7 +28,7 @@ bool can_set_direct_map(void) >>>> * protect/unprotect single pages. >>>> */ >>>> return (rodata_enabled && rodata_full) || debug_pagealloc_enabled() || >>>> - IS_ENABLED(CONFIG_KFENCE); >>>> + kfence_enabled; >>> >>> Unfortunately this won't work, because it's possible to enable KFENCE >>> after the kernel has booted with e.g.: echo 100 > >>> /sys/module/kfence/parameters/sample_interval >> Yeah, got it. Thanks for catching it. >>> >>> What is the problem you have encountered? Is the page-granular direct >>> map causing issues? >> We're working on a low memory target, page-granular mapping costed more (2M >> per 1GB) memory. Due to GKI constraints, it is not easy to disable >> CONFIG_KFENCE. So my intention was to move the judgement to runtime >> configurable w/ CONFIG_KFENCE on... >> >> Do you have any further suggestion/proposal on this? Many Thanks! > > Just to check, the cost is because we're mapping *all* of memory at page > granulatrity, right? If we were to just map the KFENCE region a page > granularity, would that be a sufficient saving? Yes,that's expected saving which I would like to address here. > > We didn't do that so far because it was simpler to just map everything at page > granularity (and that's also required by rodata_full, which I though android > used?). Yes, by default we're setting rodata_full. While for low-ram target, we also can lower the security requirement. This is why I am pursuing.. BTW, rodata_full can be easily runtime configured through bootargs. > > If it's really important (and rodata_full isn't being used), we could try to do > that. > > To do that we'd need to choose the KFENCE region *before* arm64 creates the > fine-grain translation tables, which probable needs an arch_ hook. It sounds a good solution. Let me also dig into this. Many Thanks! > > Thanks, > Mark. >
diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c index 79dd201..208d780 100644 --- a/arch/arm64/mm/pageattr.c +++ b/arch/arm64/mm/pageattr.c @@ -7,6 +7,7 @@ #include <linux/module.h> #include <linux/sched.h> #include <linux/vmalloc.h> +#include <linux/kfence.h> #include <asm/cacheflush.h> #include <asm/set_memory.h> @@ -27,7 +28,7 @@ bool can_set_direct_map(void) * protect/unprotect single pages. */ return (rodata_enabled && rodata_full) || debug_pagealloc_enabled() || - IS_ENABLED(CONFIG_KFENCE); + kfence_enabled; } static int change_page_range(pte_t *ptep, unsigned long addr, void *data) diff --git a/include/linux/kfence.h b/include/linux/kfence.h index 726857a..9fac824 100644 --- a/include/linux/kfence.h +++ b/include/linux/kfence.h @@ -26,6 +26,7 @@ extern unsigned long kfence_sample_interval; */ #define KFENCE_POOL_SIZE ((CONFIG_KFENCE_NUM_OBJECTS + 1) * 2 * PAGE_SIZE) extern char *__kfence_pool; +extern bool kfence_enabled; DECLARE_STATIC_KEY_FALSE(kfence_allocation_key); extern atomic_t kfence_allocation_gate; @@ -222,6 +223,7 @@ bool __kfence_obj_info(struct kmem_obj_info *kpp, void *object, struct slab *sla #else /* CONFIG_KFENCE */ +#define kfence_enabled 0 static inline bool is_kfence_address(const void *addr) { return false; } static inline void kfence_alloc_pool(void) { } static inline void kfence_init(void) { } diff --git a/mm/kfence/core.c b/mm/kfence/core.c index 5349c37..e5bf93d 100644 --- a/mm/kfence/core.c +++ b/mm/kfence/core.c @@ -48,7 +48,7 @@ /* === Data ================================================================= */ -static bool kfence_enabled __read_mostly; +bool kfence_enabled __read_mostly; static bool disabled_by_warn __read_mostly; unsigned long kfence_sample_interval __read_mostly = CONFIG_KFENCE_SAMPLE_INTERVAL;
Export the variable to ease the judgement of whether kfence enabled at runtime. It should be more precise than through kernel config "CONFIG_KFENCE". For example We can disable kfence at runtime using bootargs "kfence.sample_interval=0" but CONFIG_KFENCE enabled. It was false positive. Signed-off-by: Zhenhua Huang <quic_zhenhuah@quicinc.com> --- arch/arm64/mm/pageattr.c | 3 ++- include/linux/kfence.h | 2 ++ mm/kfence/core.c | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-)