0

I am working on an embedded Linux system (kernel-5.10.24), and I am trying to understand how does kmemleak work.

According to the document, the kmemleak scan the data section to check if there is unreferenced memory, and the kernel code is as follows,

kmemleak_scan()

    /*
     * Struct page scanning for each node.
     */
    get_online_mems();
    for_each_populated_zone(zone) {
        unsigned long start_pfn = zone->zone_start_pfn;
        unsigned long end_pfn = zone_end_pfn(zone);
        unsigned long pfn;

        for (pfn = start_pfn; pfn < end_pfn; pfn++) {
            struct page *page = pfn_to_online_page(pfn);

            if (!page)
                continue;

            /* only scan pages belonging to this zone */
            if (page_zone(page) != zone)
                continue;
            /* only scan if page is in use */
            if (page_count(page) == 0)
                continue;
            scan_block(page, page + 1, NULL);
            if (!(pfn & 63))
                cond_resched();
        }
    }
    put_online_mems();

It gets pointer to struct page of each PFN, and passes it to scan_block.

And the scan_block()

/*
 * Scan a memory block (exclusive range) for valid pointers and add those
 * found to the gray list.
 */
static void scan_block(void *_start, void *_end,
               struct kmemleak_object *scanned)
{
    unsigned long *ptr;
    unsigned long *start = PTR_ALIGN(_start, BYTES_PER_POINTER);
    unsigned long *end = _end - (BYTES_PER_POINTER - 1);
    unsigned long flags;
    unsigned long untagged_ptr;

    raw_spin_lock_irqsave(&kmemleak_lock, flags);
    for (ptr = start; ptr < end; ptr++) {
        struct kmemleak_object *object;
        unsigned long pointer;
        unsigned long excess_ref;

        if (scan_should_stop())
            break;

        kasan_disable_current();
        pointer = *ptr;     ///// ?????
        kasan_enable_current();

        untagged_ptr = (unsigned long)kasan_reset_tag((void *)pointer);
        if (untagged_ptr < min_addr || untagged_ptr >= max_addr)
            continue;

        /*
         * No need for get_object() here since we hold kmemleak_lock.
         * object->use_count cannot be dropped to 0 while the object
         * is still present in object_tree_root and object_list
         * (with updates protected by kmemleak_lock).
         */
        object = lookup_object(pointer, 1);

The pointer to struct page is casted to unsigned long *, and de-referenced the unsigned long * to get the pointer as the memory address to check.

My puzzlement comes from the de-reference the pointer to struct page, which is a structure to describe the PFN. Why de-referencing it can get the memory address, instead of the structure page?

In my system, the size of struct page is 32 bytes, so the page+1 is only page+0x20 instead of being increased by page_size (0x1000).

1 Answer 1

0

The pointer to struct page is a memory address. For example. 0x00a0000. page+1 is another address, say 0x00a0020.

Then this function just scans all "potential" memory pointers from 0x00a000 to 0x00a0020. It doesn't know anything about the format of struct page, except assuming pointers are aligned a certain way.

1
  • So why kernel chooses to use this way to scan 'potential' memory pointers? What does pointer to struct page specially mean? In my system there are 128MB RAM (end_pfn=0x8000), the kmemleak_scan loops from ` pfn[0x0] == page: 80fb2800, page+1: 80fb2820` to pfn[0x7fff] == page: 810b27e0, page+1: 810b2800,, the scanned size is only 0x100000 ???
    – wangt13
    Jan 5 at 0:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .