[Crash-utility] [PATCH] Fix the "kmem -s" option for Linux 5.7 and later kernels

HAGIO KAZUHITO(萩尾 一仁) k-hagio-ab at nec.com
Fri May 28 08:43:29 UTC 2021


Hi Lianbo,

-----Original Message-----
> Linux 5.7 and later kernels that contain kernel commit <1ad53d9fa3f6>
> ("slub: improve bit diffusion for freelist ptr obfuscation") changed
> the calculation formula in the freelist_ptr(), which added a swab()
> call to mix bits a little more. When kernel is built with the
> "CONFIG_SLAB_FREELIST_HARDENED=y",the "kmem -s" option fails with the
> following errors, if there is no such patch.
> 
> crash> kmem -s
> CACHE             OBJSIZE  ALLOCATED     TOTAL  SLABS  SSIZE  NAME
> 82166d00              144          0         0      0     4k  fuse_request
> 82166e00              792          0         0      0    16k  fuse_inode
> 87201e00              528          0         0      0     8k  xfs_dqtrx
> 87201f00              496          0         0      0     8k  xfs_dquot
> kmem: xfs_buf: slab: 37202e6e900 invalid freepointer: b844bab900001d70
> kmem: xfs_buf: slab: 3720250fd80 invalid freepointer: b8603f9400001370
> ...

Good catch!  And the patch diff looks good to me.

But the freelist_ptr() function, which is patched, is called only when
the error message is NOT printed.  So it seems like the patch does not
stop the message, right?

static ulong
get_freepointer(struct meminfo *si, void *object)
{
        ulong vaddr, nextfree;

        vaddr = (ulong)(object + si->slab_offset);
        if (!readmem(vaddr, KVADDR, &nextfree,
           sizeof(void *), "get_freepointer", QUIET|RETURN_ON_ERROR)) {
                error(INFO, "%s: slab: %lx invalid freepointer: %lx\n",
                        si->curname, si->slab, vaddr);
                return BADADDR;
        }

        return (freelist_ptr(si, nextfree, vaddr));
}

If so, please fix the commit message.  What is the phenomenon that
the patch fixes?

Thanks,
Kazu

> 
> Signed-off-by: Lianbo Jiang <lijiang at redhat.com>
> ---
>  memory.c | 9 +++++++--
>  1 file changed, 7 insertions(+), 2 deletions(-)
> 
> diff --git a/memory.c b/memory.c
> index 8c6bbe409922..a3cf8a86728d 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -20,6 +20,7 @@
>  #include <sys/mman.h>
>  #include <ctype.h>
>  #include <netinet/in.h>
> +#include <byteswap.h>
> 
>  struct meminfo {           /* general purpose memory information structure */
>          ulong cache;       /* used by the various memory searching/dumping */
> @@ -19336,10 +19337,14 @@ count_free_objects(struct meminfo *si, ulong freelist)
>  static ulong
>  freelist_ptr(struct meminfo *si, ulong ptr, ulong ptr_addr)
>  {
> -	if (VALID_MEMBER(kmem_cache_random))
> +	if (VALID_MEMBER(kmem_cache_random)) {
>  		/* CONFIG_SLAB_FREELIST_HARDENED */
> +
> +		if (THIS_KERNEL_VERSION >= LINUX(5,7,0))
> +			ptr_addr = (sizeof(long) == 8) ? bswap_64(ptr_addr)
> +						       : bswap_32(ptr_addr);
>  		return (ptr ^ si->random ^ ptr_addr);
> -	else
> +	} else
>  		return ptr;
>  }
> 
> --
> 2.17.1





More information about the Crash-utility mailing list