0

Trying to understand Linux slab allocator internals. But unable to dereference struct kmem_cache structure. Dont know what wrong I am doing here. I might be very silly coding bug (sorry for that) or some deep concept which I dont know. I thought it would be really easy to print fields of struct kmem_cache. My intention was to access its "list" field. But not even able to print its name.

I tried to dig deeper in source tree, to see if struct kmem_cache is of typedef (as mentioned in this post : dereferencing Pointer to incomplete type struct) , but no it is simple structure.

crash> kmem_cache
kmem_cache = $1 = (struct kmem_cache *) 0xffff9fdac0002000
crash> struct kmem_cache
struct kmem_cache {
    struct kmem_cache_cpu *cpu_slab;
    slab_flags_t flags;
    unsigned long min_partial;
    unsigned int size;
...

Linux 5.4.0-135-generic #152-Ubuntu SMP Wed Nov 23 20:19:22 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

Source : kmem_cache.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>

typedef struct {
        int             a;
        int             b;
} mytype_t;

static mytype_t                 *obj;
static struct kmem_cache        *s_cache;

static int __init
start(
        void)
{

        s_cache = kmem_cache_create("SAMPLE_CACHE", sizeof (mytype_t), 0, SLAB_POISON, NULL);
        if (!s_cache) {
                printk(KERN_ERR "kmem_cache_create failed.\n");
                return -ENOMEM;
        }
        obj = kmem_cache_alloc(s_cache, 0);
        if (!obj) {
                printk(KERN_ERR "kmem_cache_alloc failed.\n");
                return -ENOMEM;
        }
        printk(KERN_INFO "(%x) (%x)\n", obj->a, obj->b);
        printk(KERN_INFO "cache name : %s\n", s_cache->name);
        return 0;
}

static void __exit
end(
        void)
{
        kmem_cache_free(s_cache, obj);
        kmem_cache_destroy(s_cache);
        return;
}

module_init(start);
module_exit(end);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Unknown");

Makefile

obj-m := kmem_cache.o
  
KDIR := /lib/modules/$(shell uname -r)/build/

all:
        make -C $(KDIR) M=$(PWD) modules
clean:
        make -C $(KDIR) M=$(PWD) clean

Compilation error:

# make

make -C /lib/modules/5.4.0-135-generic/build/ M=/root/ldd/slab/kmem_cache modules
make[1]: Entering directory '/usr/src/linux-headers-5.4.0-135-generic'
  CC [M]  /root/ldd/slab/kmem_cache/kmem_cache.o
/root/ldd/slab/kmem_cache/kmem_cache.c: In function ‘start’:
/root/ldd/slab/kmem_cache/kmem_cache.c:29:47: error: dereferencing pointer to incomplete type ‘struct kmem_cache’
   29 |  printk(KERN_INFO "cache name : %s\n", s_cache->name);
      |                                               ^~
make[2]: *** [scripts/Makefile.build:270: /root/ldd/slab/kmem_cache/kmem_cache.o] Error 1
make[1]: *** [Makefile:1765: /root/ldd/slab/kmem_cache] Error 2
make[1]: Leaving directory '/usr/src/linux-headers-5.4.0-135-generic'
make: *** [Makefile:6: all] Error 2
MankPan
  • 79
  • 6
  • 3
    You probably just have to find and `#include` the proper header file that defines `struct kmem_cache`. I don't have access right now to Linux kernel sources to say what file that is, however. – Andrew Henle Feb 07 '23 at 11:51
  • you need to include the header where the struct is defined – user253751 Feb 07 '23 at 11:53
  • I tried to include #include But it was giving me error: field ‘memcg_params’ has incomplete type 76 | struct memcg_cache_params memcg_params; – MankPan Feb 07 '23 at 12:00
  • Link for linux source tree: https://elixir.bootlin.com/linux/v5.4.135/A/ident/kmem_cache – MankPan Feb 07 '23 at 12:00
  • Because you need to find a **proper** header which is low-level and public enough at the same time. But if you are using a pointer, why do you need header to begin with? – 0andriy Feb 07 '23 at 12:56
  • kmem_cache has multiple definitions depending on config. See description https://elixir.bootlin.com/linux/v5.4.135/source/mm/slab.h#L10 – stark Feb 07 '23 at 14:22

0 Answers0