diff mbox series

[v3,4/4] slub: Force on no_hash_pointers when slub_debug is enabled

Message ID 20210601182202.3011020-5-swboyd@chromium.org (mailing list archive)
State New, archived
Headers show
Series slub: Print non-hashed pointers in slub debugging | expand

Commit Message

Stephen Boyd June 1, 2021, 6:22 p.m. UTC
Obscuring the pointers that slub shows when debugging makes for some
confusing slub debug messages:

 Padding overwritten. 0x0000000079f0674a-0x000000000d4dce17

Those addresses are hashed for kernel security reasons. If we're trying
to be secure with slub_debug on the commandline we have some big
problems given that we dump whole chunks of kernel memory to the kernel
logs. Let's force on the no_hash_pointers commandline flag when
slub_debug is on the commandline. This makes slub debug messages more
meaningful and if by chance a kernel address is in some slub debug
object dump we will have a better chance of figuring out what went
wrong.

Note that we don't use %px in the slub code because we want to reduce
the number of places that %px is used in the kernel. This also nicely
prints a big fat warning at kernel boot if slub_debug is on the
commandline so that we know that this kernel shouldn't be used on
production systems.

Signed-off-by: Stephen Boyd <swboyd@chromium.org>
---
 include/linux/kernel.h | 2 ++
 lib/vsprintf.c         | 2 +-
 mm/slub.c              | 4 ++++
 3 files changed, 7 insertions(+), 1 deletion(-)

Comments

kernel test robot June 1, 2021, 10:45 p.m. UTC | #1
Hi Stephen,

I love your patch! Yet something to improve:

[auto build test ERROR on d07f6ca923ea0927a1024dfccafc5b53b61cfecc]

url:    https://github.com/0day-ci/linux/commits/Stephen-Boyd/slub-Print-non-hashed-pointers-in-slub-debugging/20210602-022255
base:   d07f6ca923ea0927a1024dfccafc5b53b61cfecc
config: s390-randconfig-r036-20210601 (attached as .config)
compiler: clang version 13.0.0 (https://github.com/llvm/llvm-project db26cd30b6dd65e88d786e97a1e453af5cd48966)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install s390 cross compiling tool for clang build
        # apt-get install binutils-s390x-linux-gnu
        # https://github.com/0day-ci/linux/commit/ab6ede356a6f366690b4a4e9dd597b63be241ad0
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Stephen-Boyd/slub-Print-non-hashed-pointers-in-slub-debugging/20210602-022255
        git checkout ab6ede356a6f366690b4a4e9dd597b63be241ad0
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=s390 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   In file included from mm/slub.c:14:
   In file included from include/linux/swap.h:9:
   In file included from include/linux/memcontrol.h:22:
   In file included from include/linux/writeback.h:14:
   In file included from include/linux/blk-cgroup.h:23:
   In file included from include/linux/blkdev.h:25:
   In file included from include/linux/scatterlist.h:9:
   In file included from arch/s390/include/asm/io.h:75:
   include/asm-generic/io.h:464:31: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           val = __raw_readb(PCI_IOBASE + addr);
                             ~~~~~~~~~~ ^
   include/asm-generic/io.h:477:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           val = __le16_to_cpu((__le16 __force)__raw_readw(PCI_IOBASE + addr));
                                                           ~~~~~~~~~~ ^
   include/uapi/linux/byteorder/big_endian.h:36:59: note: expanded from macro '__le16_to_cpu'
   #define __le16_to_cpu(x) __swab16((__force __u16)(__le16)(x))
                                                             ^
   include/uapi/linux/swab.h:102:54: note: expanded from macro '__swab16'
   #define __swab16(x) (__u16)__builtin_bswap16((__u16)(x))
                                                        ^
   In file included from mm/slub.c:14:
   In file included from include/linux/swap.h:9:
   In file included from include/linux/memcontrol.h:22:
   In file included from include/linux/writeback.h:14:
   In file included from include/linux/blk-cgroup.h:23:
   In file included from include/linux/blkdev.h:25:
   In file included from include/linux/scatterlist.h:9:
   In file included from arch/s390/include/asm/io.h:75:
   include/asm-generic/io.h:490:61: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           val = __le32_to_cpu((__le32 __force)__raw_readl(PCI_IOBASE + addr));
                                                           ~~~~~~~~~~ ^
   include/uapi/linux/byteorder/big_endian.h:34:59: note: expanded from macro '__le32_to_cpu'
   #define __le32_to_cpu(x) __swab32((__force __u32)(__le32)(x))
                                                             ^
   include/uapi/linux/swab.h:115:54: note: expanded from macro '__swab32'
   #define __swab32(x) (__u32)__builtin_bswap32((__u32)(x))
                                                        ^
   In file included from mm/slub.c:14:
   In file included from include/linux/swap.h:9:
   In file included from include/linux/memcontrol.h:22:
   In file included from include/linux/writeback.h:14:
   In file included from include/linux/blk-cgroup.h:23:
   In file included from include/linux/blkdev.h:25:
   In file included from include/linux/scatterlist.h:9:
   In file included from arch/s390/include/asm/io.h:75:
   include/asm-generic/io.h:501:33: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           __raw_writeb(value, PCI_IOBASE + addr);
                               ~~~~~~~~~~ ^
   include/asm-generic/io.h:511:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           __raw_writew((u16 __force)cpu_to_le16(value), PCI_IOBASE + addr);
                                                         ~~~~~~~~~~ ^
   include/asm-generic/io.h:521:59: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           __raw_writel((u32 __force)cpu_to_le32(value), PCI_IOBASE + addr);
                                                         ~~~~~~~~~~ ^
   include/asm-generic/io.h:609:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           readsb(PCI_IOBASE + addr, buffer, count);
                  ~~~~~~~~~~ ^
   include/asm-generic/io.h:617:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           readsw(PCI_IOBASE + addr, buffer, count);
                  ~~~~~~~~~~ ^
   include/asm-generic/io.h:625:20: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           readsl(PCI_IOBASE + addr, buffer, count);
                  ~~~~~~~~~~ ^
   include/asm-generic/io.h:634:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           writesb(PCI_IOBASE + addr, buffer, count);
                   ~~~~~~~~~~ ^
   include/asm-generic/io.h:643:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           writesw(PCI_IOBASE + addr, buffer, count);
                   ~~~~~~~~~~ ^
   include/asm-generic/io.h:652:21: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           writesl(PCI_IOBASE + addr, buffer, count);
                   ~~~~~~~~~~ ^
>> mm/slub.c:4464:30: error: use of undeclared identifier 'slub_debug_enabled'
           if (static_branch_unlikely(&slub_debug_enabled))
                                       ^
>> mm/slub.c:4464:30: error: use of undeclared identifier 'slub_debug_enabled'
>> mm/slub.c:4464:30: error: use of undeclared identifier 'slub_debug_enabled'
>> mm/slub.c:4464:30: error: use of undeclared identifier 'slub_debug_enabled'
>> mm/slub.c:4464:6: error: invalid argument type 'void' to unary expression
           if (static_branch_unlikely(&slub_debug_enabled))
               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/jump_label.h:496:35: note: expanded from macro 'static_branch_unlikely'
   #define static_branch_unlikely(x)       unlikely_notrace(static_key_enabled(&(x)->key))
                                           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/compiler.h:80:30: note: expanded from macro 'unlikely_notrace'
   # define unlikely_notrace(x)    unlikely(x)
                                   ^~~~~~~~~~~
   include/linux/compiler.h:78:40: note: expanded from macro 'unlikely'
   # define unlikely(x)    __builtin_expect(!!(x), 0)
                                             ^~~~
   12 warnings and 5 errors generated.


vim +/slub_debug_enabled +4464 mm/slub.c

  4453	
  4454	void __init kmem_cache_init(void)
  4455	{
  4456		static __initdata struct kmem_cache boot_kmem_cache,
  4457			boot_kmem_cache_node;
  4458		int node;
  4459	
  4460		if (debug_guardpage_minorder())
  4461			slub_max_order = 0;
  4462	
  4463		/* Print slub debugging pointers without hashing */
> 4464		if (static_branch_unlikely(&slub_debug_enabled))
  4465			no_hash_pointers_enable(NULL);
  4466	
  4467		kmem_cache_node = &boot_kmem_cache_node;
  4468		kmem_cache = &boot_kmem_cache;
  4469	
  4470		/*
  4471		 * Initialize the nodemask for which we will allocate per node
  4472		 * structures. Here we don't need taking slab_mutex yet.
  4473		 */
  4474		for_each_node_state(node, N_NORMAL_MEMORY)
  4475			node_set(node, slab_nodes);
  4476	
  4477		create_boot_cache(kmem_cache_node, "kmem_cache_node",
  4478			sizeof(struct kmem_cache_node), SLAB_HWCACHE_ALIGN, 0, 0);
  4479	
  4480		register_hotmemory_notifier(&slab_memory_callback_nb);
  4481	
  4482		/* Able to allocate the per node structures */
  4483		slab_state = PARTIAL;
  4484	
  4485		create_boot_cache(kmem_cache, "kmem_cache",
  4486				offsetof(struct kmem_cache, node) +
  4487					nr_node_ids * sizeof(struct kmem_cache_node *),
  4488			       SLAB_HWCACHE_ALIGN, 0, 0);
  4489	
  4490		kmem_cache = bootstrap(&boot_kmem_cache);
  4491		kmem_cache_node = bootstrap(&boot_kmem_cache_node);
  4492	
  4493		/* Now we can use the kmem_cache to allocate kmalloc slabs */
  4494		setup_kmalloc_cache_index_table();
  4495		create_kmalloc_caches(0);
  4496	
  4497		/* Setup random freelists for each cache */
  4498		init_freelist_randomization();
  4499	
  4500		cpuhp_setup_state_nocalls(CPUHP_SLUB_DEAD, "slub:dead", NULL,
  4501					  slub_cpu_dead);
  4502	
  4503		pr_info("SLUB: HWalign=%d, Order=%u-%u, MinObjects=%u, CPUs=%u, Nodes=%u\n",
  4504			cache_line_size(),
  4505			slub_min_order, slub_max_order, slub_min_objects,
  4506			nr_cpu_ids, nr_node_ids);
  4507	}
  4508	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
Andrew Morton June 2, 2021, 12:26 a.m. UTC | #2
On Wed, 2 Jun 2021 06:45:55 +0800 kernel test robot <lkp@intel.com> wrote:

> >> mm/slub.c:4464:30: error: use of undeclared identifier 'slub_debug_enabled'
>            if (static_branch_unlikely(&slub_debug_enabled))
>                                        ^
> >> mm/slub.c:4464:30: error: use of undeclared identifier 'slub_debug_enabled'
> >> mm/slub.c:4464:30: error: use of undeclared identifier 'slub_debug_enabled'
> >> mm/slub.c:4464:30: error: use of undeclared identifier 'slub_debug_enabled'
> >> mm/slub.c:4464:6: error: invalid argument type 'void' to unary expression
>            if (static_branch_unlikely(&slub_debug_enabled))
>                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Thanks.  Stephen, how about this?

--- a/mm/slub.c~slub-force-on-no_hash_pointers-when-slub_debug-is-enabled-fix
+++ a/mm/slub.c
@@ -117,12 +117,26 @@
  */
 
 #ifdef CONFIG_SLUB_DEBUG
+
 #ifdef CONFIG_SLUB_DEBUG_ON
 DEFINE_STATIC_KEY_TRUE(slub_debug_enabled);
 #else
 DEFINE_STATIC_KEY_FALSE(slub_debug_enabled);
 #endif
-#endif
+
+static inline bool __slub_debug_enabled(void)
+{
+	return static_branch_unlikely(&slub_debug_enabled);
+}
+
+#else		/* CONFIG_SLUB_DEBUG */
+
+static inline bool __slub_debug_enabled(void)
+{
+	return false;
+}
+
+#endif		/* CONFIG_SLUB_DEBUG */
 
 static inline bool kmem_cache_debug(struct kmem_cache *s)
 {
@@ -4493,7 +4507,7 @@ void __init kmem_cache_init(void)
 		slub_max_order = 0;
 
 	/* Print slub debugging pointers without hashing */
-	if (static_branch_unlikely(&slub_debug_enabled))
+	if (__slub_debug_enabled())
 		no_hash_pointers_enable(NULL);
 
 	kmem_cache_node = &boot_kmem_cache_node;
Stephen Boyd June 2, 2021, 1:03 a.m. UTC | #3
Quoting Andrew Morton (2021-06-01 17:26:59)
> On Wed, 2 Jun 2021 06:45:55 +0800 kernel test robot <lkp@intel.com> wrote:
>
> > >> mm/slub.c:4464:30: error: use of undeclared identifier 'slub_debug_enabled'
> >            if (static_branch_unlikely(&slub_debug_enabled))
> >                                        ^
> > >> mm/slub.c:4464:30: error: use of undeclared identifier 'slub_debug_enabled'
> > >> mm/slub.c:4464:30: error: use of undeclared identifier 'slub_debug_enabled'
> > >> mm/slub.c:4464:30: error: use of undeclared identifier 'slub_debug_enabled'
> > >> mm/slub.c:4464:6: error: invalid argument type 'void' to unary expression
> >            if (static_branch_unlikely(&slub_debug_enabled))
> >                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>
> Thanks.  Stephen, how about this?

Looks good to me. Thanks for the quick fix!

>
> --- a/mm/slub.c~slub-force-on-no_hash_pointers-when-slub_debug-is-enabled-fix
> +++ a/mm/slub.c
> @@ -117,12 +117,26 @@
>   */
>
>  #ifdef CONFIG_SLUB_DEBUG
> +
>  #ifdef CONFIG_SLUB_DEBUG_ON
>  DEFINE_STATIC_KEY_TRUE(slub_debug_enabled);
>  #else
>  DEFINE_STATIC_KEY_FALSE(slub_debug_enabled);
>  #endif
> -#endif
> +
> +static inline bool __slub_debug_enabled(void)
> +{
> +       return static_branch_unlikely(&slub_debug_enabled);

To make this even better it could be

	return static_branch_maybe(CONFIG_SLUB_DEBUG_ON, &slub_debug_enabled);

> +}
> +
> +#else          /* CONFIG_SLUB_DEBUG */
> +
> +static inline bool __slub_debug_enabled(void)
> +{
> +       return false;
> +}
> +
> +#endif         /* CONFIG_SLUB_DEBUG */
>
>  static inline bool kmem_cache_debug(struct kmem_cache *s)
>  {
> @@ -4493,7 +4507,7 @@ void __init kmem_cache_init(void)
>                 slub_max_order = 0;
>
>         /* Print slub debugging pointers without hashing */
> -       if (static_branch_unlikely(&slub_debug_enabled))
> +       if (__slub_debug_enabled())

It would be super cool if static branches could be optimized out when
they're never changed by any code, nor exported to code, just tested in
conditions. I've no idea if that is the case though.

>                 no_hash_pointers_enable(NULL);
>
>         kmem_cache_node = &boot_kmem_cache_node;
Vlastimil Babka June 2, 2021, 10:48 a.m. UTC | #4
On 6/2/21 3:03 AM, Stephen Boyd wrote:
> Quoting Andrew Morton (2021-06-01 17:26:59)
>> On Wed, 2 Jun 2021 06:45:55 +0800 kernel test robot <lkp@intel.com> wrote:
>>
>> > >> mm/slub.c:4464:30: error: use of undeclared identifier 'slub_debug_enabled'
>> >            if (static_branch_unlikely(&slub_debug_enabled))
>> >                                        ^
>> > >> mm/slub.c:4464:30: error: use of undeclared identifier 'slub_debug_enabled'
>> > >> mm/slub.c:4464:30: error: use of undeclared identifier 'slub_debug_enabled'
>> > >> mm/slub.c:4464:30: error: use of undeclared identifier 'slub_debug_enabled'
>> > >> mm/slub.c:4464:6: error: invalid argument type 'void' to unary expression
>> >            if (static_branch_unlikely(&slub_debug_enabled))
>> >                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>
>> Thanks.  Stephen, how about this?
> 
> Looks good to me. Thanks for the quick fix!
> 
>>
>> --- a/mm/slub.c~slub-force-on-no_hash_pointers-when-slub_debug-is-enabled-fix
>> +++ a/mm/slub.c
>> @@ -117,12 +117,26 @@
>>   */
>>
>>  #ifdef CONFIG_SLUB_DEBUG
>> +
>>  #ifdef CONFIG_SLUB_DEBUG_ON
>>  DEFINE_STATIC_KEY_TRUE(slub_debug_enabled);
>>  #else
>>  DEFINE_STATIC_KEY_FALSE(slub_debug_enabled);
>>  #endif
>> -#endif
>> +
>> +static inline bool __slub_debug_enabled(void)
>> +{
>> +       return static_branch_unlikely(&slub_debug_enabled);
> 
> To make this even better it could be
> 
> 	return static_branch_maybe(CONFIG_SLUB_DEBUG_ON, &slub_debug_enabled);
> 
>> +}
>> +
>> +#else          /* CONFIG_SLUB_DEBUG */
>> +
>> +static inline bool __slub_debug_enabled(void)
>> +{
>> +       return false;
>> +}
>> +
>> +#endif         /* CONFIG_SLUB_DEBUG */
>>
>>  static inline bool kmem_cache_debug(struct kmem_cache *s)
>>  {
>> @@ -4493,7 +4507,7 @@ void __init kmem_cache_init(void)
>>                 slub_max_order = 0;
>>
>>         /* Print slub debugging pointers without hashing */
>> -       if (static_branch_unlikely(&slub_debug_enabled))
>> +       if (__slub_debug_enabled())

A minimal fix would be to put this under #ifdef CONFIG_SLUB_DEBUG
and use static_key_enabled() as we don't need the jump label optimization for
init code. But the current fix works.

> 
> It would be super cool if static branches could be optimized out when
> they're never changed by any code, nor exported to code, just tested in
> conditions. I've no idea if that is the case though.
> 
>>                 no_hash_pointers_enable(NULL);
>>
>>         kmem_cache_node = &boot_kmem_cache_node;
>
Vlastimil Babka June 2, 2021, 10:50 a.m. UTC | #5
On 6/1/21 8:22 PM, Stephen Boyd wrote:
> Obscuring the pointers that slub shows when debugging makes for some
> confusing slub debug messages:
> 
>  Padding overwritten. 0x0000000079f0674a-0x000000000d4dce17
> 
> Those addresses are hashed for kernel security reasons. If we're trying
> to be secure with slub_debug on the commandline we have some big
> problems given that we dump whole chunks of kernel memory to the kernel
> logs. Let's force on the no_hash_pointers commandline flag when
> slub_debug is on the commandline. This makes slub debug messages more
> meaningful and if by chance a kernel address is in some slub debug
> object dump we will have a better chance of figuring out what went
> wrong.
> 
> Note that we don't use %px in the slub code because we want to reduce
> the number of places that %px is used in the kernel. This also nicely
> prints a big fat warning at kernel boot if slub_debug is on the
> commandline so that we know that this kernel shouldn't be used on
> production systems.
> 
> Signed-off-by: Stephen Boyd <swboyd@chromium.org>

Acked-by: Vlastimil Babka <vbabka@suse.cz>

> ---
>  include/linux/kernel.h | 2 ++
>  lib/vsprintf.c         | 2 +-
>  mm/slub.c              | 4 ++++
>  3 files changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/include/linux/kernel.h b/include/linux/kernel.h
> index 15d8bad3d2f2..bf950621febf 100644
> --- a/include/linux/kernel.h
> +++ b/include/linux/kernel.h
> @@ -357,6 +357,8 @@ int sscanf(const char *, const char *, ...);
>  extern __scanf(2, 0)
>  int vsscanf(const char *, const char *, va_list);
>  
> +extern int no_hash_pointers_enable(char *str);
> +
>  extern int get_option(char **str, int *pint);
>  extern char *get_options(const char *str, int nints, int *ints);
>  extern unsigned long long memparse(const char *ptr, char **retptr);
> diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> index f0c35d9b65bf..cc281f5895f9 100644
> --- a/lib/vsprintf.c
> +++ b/lib/vsprintf.c
> @@ -2186,7 +2186,7 @@ char *fwnode_string(char *buf, char *end, struct fwnode_handle *fwnode,
>  bool no_hash_pointers __ro_after_init;
>  EXPORT_SYMBOL_GPL(no_hash_pointers);
>  
> -static int __init no_hash_pointers_enable(char *str)
> +int __init no_hash_pointers_enable(char *str)
>  {
>  	if (no_hash_pointers)
>  		return 0;
> diff --git a/mm/slub.c b/mm/slub.c
> index bf4949115412..a722794f1dbd 100644
> --- a/mm/slub.c
> +++ b/mm/slub.c
> @@ -4460,6 +4460,10 @@ void __init kmem_cache_init(void)
>  	if (debug_guardpage_minorder())
>  		slub_max_order = 0;
>  
> +	/* Print slub debugging pointers without hashing */
> +	if (static_branch_unlikely(&slub_debug_enabled))
> +		no_hash_pointers_enable(NULL);
> +
>  	kmem_cache_node = &boot_kmem_cache_node;
>  	kmem_cache = &boot_kmem_cache;
>  
>
Petr Mladek June 3, 2021, 1:15 p.m. UTC | #6
On Tue 2021-06-01 11:22:02, Stephen Boyd wrote:
> Obscuring the pointers that slub shows when debugging makes for some
> confusing slub debug messages:
> 
>  Padding overwritten. 0x0000000079f0674a-0x000000000d4dce17
> 
> Those addresses are hashed for kernel security reasons. If we're trying
> to be secure with slub_debug on the commandline we have some big
> problems given that we dump whole chunks of kernel memory to the kernel
> logs. Let's force on the no_hash_pointers commandline flag when
> slub_debug is on the commandline. This makes slub debug messages more
> meaningful and if by chance a kernel address is in some slub debug
> object dump we will have a better chance of figuring out what went
> wrong.
> 
> Note that we don't use %px in the slub code because we want to reduce
> the number of places that %px is used in the kernel. This also nicely
> prints a big fat warning at kernel boot if slub_debug is on the
> commandline so that we know that this kernel shouldn't be used on
> production systems.
> 
> Signed-off-by: Stephen Boyd <swboyd@chromium.org>

Acked-by: Petr Mladek <pmladek@suse.com>

Best Regards,
Petr
Kees Cook Sept. 20, 2021, 2:29 p.m. UTC | #7
On Tue, Jun 01, 2021 at 11:22:02AM -0700, Stephen Boyd wrote:
> Obscuring the pointers that slub shows when debugging makes for some
> confusing slub debug messages:
> 
>  Padding overwritten. 0x0000000079f0674a-0x000000000d4dce17
> 
> Those addresses are hashed for kernel security reasons. If we're trying
> to be secure with slub_debug on the commandline we have some big
> problems given that we dump whole chunks of kernel memory to the kernel
> logs. Let's force on the no_hash_pointers commandline flag when
> slub_debug is on the commandline. This makes slub debug messages more
> meaningful and if by chance a kernel address is in some slub debug
> object dump we will have a better chance of figuring out what went
> wrong.
> 
> Note that we don't use %px in the slub code because we want to reduce
> the number of places that %px is used in the kernel. This also nicely
> prints a big fat warning at kernel boot if slub_debug is on the
> commandline so that we know that this kernel shouldn't be used on
> production systems.

Eeeek. I missed this patch. NAK NAK. People use slub_debug for
production systems to gain redzoning, etc, as a layer of defense, and
they absolutely do not want %p-hashing disabled. %p hashing is
controlled by the no_hash_pointers boot param (since v5.12), and needs to stay
separate from slub_debug.

Can we please revert this in Linus's tree and in v5.14?

-Kees

> 
> Signed-off-by: Stephen Boyd <swboyd@chromium.org>
> ---
>  include/linux/kernel.h | 2 ++
>  lib/vsprintf.c         | 2 +-
>  mm/slub.c              | 4 ++++
>  3 files changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/include/linux/kernel.h b/include/linux/kernel.h
> index 15d8bad3d2f2..bf950621febf 100644
> --- a/include/linux/kernel.h
> +++ b/include/linux/kernel.h
> @@ -357,6 +357,8 @@ int sscanf(const char *, const char *, ...);
>  extern __scanf(2, 0)
>  int vsscanf(const char *, const char *, va_list);
>  
> +extern int no_hash_pointers_enable(char *str);
> +
>  extern int get_option(char **str, int *pint);
>  extern char *get_options(const char *str, int nints, int *ints);
>  extern unsigned long long memparse(const char *ptr, char **retptr);
> diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> index f0c35d9b65bf..cc281f5895f9 100644
> --- a/lib/vsprintf.c
> +++ b/lib/vsprintf.c
> @@ -2186,7 +2186,7 @@ char *fwnode_string(char *buf, char *end, struct fwnode_handle *fwnode,
>  bool no_hash_pointers __ro_after_init;
>  EXPORT_SYMBOL_GPL(no_hash_pointers);
>  
> -static int __init no_hash_pointers_enable(char *str)
> +int __init no_hash_pointers_enable(char *str)
>  {
>  	if (no_hash_pointers)
>  		return 0;
> diff --git a/mm/slub.c b/mm/slub.c
> index bf4949115412..a722794f1dbd 100644
> --- a/mm/slub.c
> +++ b/mm/slub.c
> @@ -4460,6 +4460,10 @@ void __init kmem_cache_init(void)
>  	if (debug_guardpage_minorder())
>  		slub_max_order = 0;
>  
> +	/* Print slub debugging pointers without hashing */
> +	if (static_branch_unlikely(&slub_debug_enabled))
> +		no_hash_pointers_enable(NULL);
> +
>  	kmem_cache_node = &boot_kmem_cache_node;
>  	kmem_cache = &boot_kmem_cache;
>  
> -- 
> https://chromeos.dev
>
Stephen Boyd Sept. 20, 2021, 6:23 p.m. UTC | #8
Quoting Kees Cook (2021-09-20 07:29:54)
> On Tue, Jun 01, 2021 at 11:22:02AM -0700, Stephen Boyd wrote:
> > Obscuring the pointers that slub shows when debugging makes for some
> > confusing slub debug messages:
> >
> >  Padding overwritten. 0x0000000079f0674a-0x000000000d4dce17
> >
> > Those addresses are hashed for kernel security reasons. If we're trying
> > to be secure with slub_debug on the commandline we have some big
> > problems given that we dump whole chunks of kernel memory to the kernel
> > logs. Let's force on the no_hash_pointers commandline flag when
> > slub_debug is on the commandline. This makes slub debug messages more
> > meaningful and if by chance a kernel address is in some slub debug
> > object dump we will have a better chance of figuring out what went
> > wrong.
> >
> > Note that we don't use %px in the slub code because we want to reduce
> > the number of places that %px is used in the kernel. This also nicely
> > prints a big fat warning at kernel boot if slub_debug is on the
> > commandline so that we know that this kernel shouldn't be used on
> > production systems.
>
> Eeeek. I missed this patch. NAK NAK. People use slub_debug for
> production systems to gain redzoning, etc, as a layer of defense, and
> they absolutely do not want %p-hashing disabled. %p hashing is
> controlled by the no_hash_pointers boot param (since v5.12), and needs to stay
> separate from slub_debug.
>
> Can we please revert this in Linus's tree and in v5.14?
>

This is fine with me as long as debugging with slub_debug on the
commandline is possible. Would you prefer v1 of this patch series[1]
that uses the printk format to print unhashed pointers in slub debugging
messages?

[1] https://lore.kernel.org/r/20210520013539.3733631-1-swboyd@chromium.org
Kees Cook Sept. 20, 2021, 6:28 p.m. UTC | #9
On Mon, Sep 20, 2021 at 11:23:01AM -0700, Stephen Boyd wrote:
> Quoting Kees Cook (2021-09-20 07:29:54)
> > On Tue, Jun 01, 2021 at 11:22:02AM -0700, Stephen Boyd wrote:
> > > Obscuring the pointers that slub shows when debugging makes for some
> > > confusing slub debug messages:
> > >
> > >  Padding overwritten. 0x0000000079f0674a-0x000000000d4dce17
> > >
> > > Those addresses are hashed for kernel security reasons. If we're trying
> > > to be secure with slub_debug on the commandline we have some big
> > > problems given that we dump whole chunks of kernel memory to the kernel
> > > logs. Let's force on the no_hash_pointers commandline flag when
> > > slub_debug is on the commandline. This makes slub debug messages more
> > > meaningful and if by chance a kernel address is in some slub debug
> > > object dump we will have a better chance of figuring out what went
> > > wrong.
> > >
> > > Note that we don't use %px in the slub code because we want to reduce
> > > the number of places that %px is used in the kernel. This also nicely
> > > prints a big fat warning at kernel boot if slub_debug is on the
> > > commandline so that we know that this kernel shouldn't be used on
> > > production systems.
> >
> > Eeeek. I missed this patch. NAK NAK. People use slub_debug for
> > production systems to gain redzoning, etc, as a layer of defense, and
> > they absolutely do not want %p-hashing disabled. %p hashing is
> > controlled by the no_hash_pointers boot param (since v5.12), and needs to stay
> > separate from slub_debug.
> >
> > Can we please revert this in Linus's tree and in v5.14?
> >
> 
> This is fine with me as long as debugging with slub_debug on the
> commandline is possible. Would you prefer v1 of this patch series[1]
> that uses the printk format to print unhashed pointers in slub debugging
> messages?
> 
> [1] https://lore.kernel.org/r/20210520013539.3733631-1-swboyd@chromium.org

I'd like to keep %px use in the kernel minimized. Seeing full pointers (%p
hashing disabled) can be done with the no_hash_pointers boot param, and
that's used in other debug cases as well. I'd rather keep it a global
knob.

Thanks!

-Kees
Stephen Boyd Sept. 20, 2021, 6:44 p.m. UTC | #10
Quoting Kees Cook (2021-09-20 11:28:50)
> On Mon, Sep 20, 2021 at 11:23:01AM -0700, Stephen Boyd wrote:
> > Quoting Kees Cook (2021-09-20 07:29:54)
> > > On Tue, Jun 01, 2021 at 11:22:02AM -0700, Stephen Boyd wrote:
> > > > Obscuring the pointers that slub shows when debugging makes for some
> > > > confusing slub debug messages:
> > > >
> > > >  Padding overwritten. 0x0000000079f0674a-0x000000000d4dce17
> > > >
> > > > Those addresses are hashed for kernel security reasons. If we're trying
> > > > to be secure with slub_debug on the commandline we have some big
> > > > problems given that we dump whole chunks of kernel memory to the kernel
> > > > logs. Let's force on the no_hash_pointers commandline flag when
> > > > slub_debug is on the commandline. This makes slub debug messages more
> > > > meaningful and if by chance a kernel address is in some slub debug
> > > > object dump we will have a better chance of figuring out what went
> > > > wrong.
> > > >
> > > > Note that we don't use %px in the slub code because we want to reduce
> > > > the number of places that %px is used in the kernel. This also nicely
> > > > prints a big fat warning at kernel boot if slub_debug is on the
> > > > commandline so that we know that this kernel shouldn't be used on
> > > > production systems.
> > >
> > > Eeeek. I missed this patch. NAK NAK. People use slub_debug for
> > > production systems to gain redzoning, etc, as a layer of defense, and
> > > they absolutely do not want %p-hashing disabled. %p hashing is
> > > controlled by the no_hash_pointers boot param (since v5.12), and needs to stay
> > > separate from slub_debug.
> > >
> > > Can we please revert this in Linus's tree and in v5.14?
> > >
> >
> > This is fine with me as long as debugging with slub_debug on the
> > commandline is possible. Would you prefer v1 of this patch series[1]
> > that uses the printk format to print unhashed pointers in slub debugging
> > messages?
> >
> > [1] https://lore.kernel.org/r/20210520013539.3733631-1-swboyd@chromium.org
>
> I'd like to keep %px use in the kernel minimized. Seeing full pointers (%p
> hashing disabled) can be done with the no_hash_pointers boot param, and
> that's used in other debug cases as well. I'd rather keep it a global
> knob.
>

Can you elaborate on your use case where slub debugging is used for
security in production systems via redzoning? Maybe that redzoning logic
in slub debug should be moved out of CONFIG_SLUB_DEBUG into slub proper?
Or maybe the config symbol should be changed to something that doesn't
have 'debug' in the name?

The main goal of this series was to make slub debug messages I saw
useful instead of confusing given that all the pointers were hashed. If
some part of slub debugging is production critical then I wonder why
it's behind a debug named config knob and why it prints so much pointer
information on production systems.
diff mbox series

Patch

diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 15d8bad3d2f2..bf950621febf 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -357,6 +357,8 @@  int sscanf(const char *, const char *, ...);
 extern __scanf(2, 0)
 int vsscanf(const char *, const char *, va_list);
 
+extern int no_hash_pointers_enable(char *str);
+
 extern int get_option(char **str, int *pint);
 extern char *get_options(const char *str, int nints, int *ints);
 extern unsigned long long memparse(const char *ptr, char **retptr);
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index f0c35d9b65bf..cc281f5895f9 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -2186,7 +2186,7 @@  char *fwnode_string(char *buf, char *end, struct fwnode_handle *fwnode,
 bool no_hash_pointers __ro_after_init;
 EXPORT_SYMBOL_GPL(no_hash_pointers);
 
-static int __init no_hash_pointers_enable(char *str)
+int __init no_hash_pointers_enable(char *str)
 {
 	if (no_hash_pointers)
 		return 0;
diff --git a/mm/slub.c b/mm/slub.c
index bf4949115412..a722794f1dbd 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -4460,6 +4460,10 @@  void __init kmem_cache_init(void)
 	if (debug_guardpage_minorder())
 		slub_max_order = 0;
 
+	/* Print slub debugging pointers without hashing */
+	if (static_branch_unlikely(&slub_debug_enabled))
+		no_hash_pointers_enable(NULL);
+
 	kmem_cache_node = &boot_kmem_cache_node;
 	kmem_cache = &boot_kmem_cache;