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(a)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