From eeaed479a438891fca96977cd64ae1166fddd38e Mon Sep 17 00:00:00 2001 From: Lianbo Jiang Date: Mon, 14 Aug 2023 09:54:24 +0800 Subject: [PATCH 27/30] Fix "kmem -s|-S" not working properly when CONFIG_SLAB_FREELIST_HARDENED is enabled Currently, crash-utility still depends on detecting the kernel version, or the asm instruction 'bswap' on x86_64/x86 architectures to decide how to deal with the freelist ptr obfuscation, when kernel option CONFIG_SLAB_FREELIST_HARDENED is enabled. As you known, the bit diffusion for freelist ptr obfuscation has experienced the changes several times on the kernel side, For most distributions, usually they might backport these kernel patches from upstream, especially for the old kernel, the 'kmem -s|-S' will fail with an error "invalid freepointer", which can be observed on ppc64le and S390x architectures, etc. That is really not friendly. Given that, let's fix the above issues this time, and it won't rely on the linux version number or asm instruction 'bswap' to decide how to dereference the freelist ptr. Reported-by: Lucas Oakley Signed-off-by: Lianbo Jiang Acked-by: Rafael Aquini --- memory.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/memory.c b/memory.c index 39f0e0ec36d2..5d76c5d7fe6f 100644 --- a/memory.c +++ b/memory.c @@ -19683,9 +19683,12 @@ freelist_ptr(struct meminfo *si, ulong ptr, ulong ptr_addr) 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); + ulong addr = (sizeof(long) == 8) ? bswap_64(ptr_addr) : bswap_32(ptr_addr); + addr = ptr ^ si->random ^ addr; + + if (!addr || accessible(addr)) + return addr; + return (ptr ^ si->random ^ ptr_addr); } else return ptr; -- 2.37.1