53 lines
1.9 KiB
Diff
53 lines
1.9 KiB
Diff
|
From eeaed479a438891fca96977cd64ae1166fddd38e Mon Sep 17 00:00:00 2001
|
||
|
From: Lianbo Jiang <lijiang@redhat.com>
|
||
|
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 <soakley@redhat.com>
|
||
|
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
|
||
|
Acked-by: Rafael Aquini <aquini@redhat.com>
|
||
|
---
|
||
|
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
|
||
|
|