[Crash-utility] [PATCH] Fix for "kmem <addr>" for kernels configured with CONFIG_SLUB and SLAB_RED_ZONE.

Dave Anderson anderson at redhat.com
Fri Feb 3 17:13:33 UTC 2017



----- Original Message -----
> Dave Anderson <anderson at redhat.com> writes:
> 
> >> I see what you say. However, my usual usage of kmem is to get the data
> >> address of object (I was thinking the most users are same usage).
> >> 
> >> 	crash> kmem <pointer in stack>
> >> 	info for data address
> >> 
> >> 	copy & paste <data address>
> >> 	crash> p *(struct inode *)<data address>
> >
> > Why not copy-and-paste the address from <pointer in stack>?  Or use "bt
> > -FF"
> > to get the kmem cache type, and skip using "kmem" entirely?  ;-)
> 
> Yes, bt -FF helps much. However, the pointer in stack is address in
> middle of object data in many times.
> 
> E.g. for ext4_inode_cache, "struct address_space *" is in stack. But
> actual slab object is inode->i_mapping == ext4_inode_info.vfs_inode.i_data.
> Or functions takes member of object, e.g., &object->list.        for (p = vaddr; p < vaddr + objects * si->size; p += si->size) {
                hq_open();
                is_free = FALSE;
                /* Search an object on both of freelist and cpu_freelist */
                ulong lists[] = { freelist, cpu_freelist, };
                for (i = 0; i < sizeof(lists) / sizeof(lists[0]); i++) {
                        for (is_free = 0, q = lists[i]; q;
                             q = get_freepointer(si, (void *)q)) {

                                if (q == BADADDR) {
                                        hq_close();
                                        return FALSE;
                                }
                                if (q & PAGE_MAPPING_ANON)
                                        break;
                                if (p == q) {
                                        is_free = TRUE;
                                        goto found_object;
                                }
                                if (!hq_enter(q)) {
                                        hq_close();
                                        error(INFO, "%s: slab: %lx duplicate freelist object: %lx\n",
                                              si->curname, si->slab, q);
                                        return FALSE;
                                }
                        }
                }
        found_object:
> 
> If there is easy way to get the object address from the field of object
> address, it would be what I want.

OK, I understand.  Let me work on a new "set redzone on/off" environment 
variable that can be toggled on-and-off during runtime. 

But I believe I see a problem in do_slab_slub().  When it is checking for free 
objects to display as FREE / [ALLOCATED], it will never find it in 4.6+ kernels
with a red_left_pad.  Note below, when it checks whether (p == q), the "q" address
is the "shifted" address seen by the kmalloc() caller, and will never match the 
base object address "p", so "is_free" never gets set:

        for (p = vaddr; p < vaddr + objects * si->size; p += si->size) {
                hq_open();
                is_free = FALSE;
                /* Search an object on both of freelist and cpu_freelist */
                ulong lists[] = { freelist, cpu_freelist, };
                for (i = 0; i < sizeof(lists) / sizeof(lists[0]); i++) {
                        for (is_free = 0, q = lists[i]; q;
                             q = get_freepointer(si, (void *)q)) {

                                if (q == BADADDR) {
                                        hq_close();
                                        return FALSE;
                                }
                                if (q & PAGE_MAPPING_ANON)
                                        break;
=== never can match ===>        if (p == q) {
                                        is_free = TRUE;
                                        goto found_object;
                                }
                                if (!hq_enter(q)) {
                                        hq_close();
                                        error(INFO, "%s: slab: %lx duplicate freelist object: %lx\n",
                                              si->curname, si->slab, q);
                                        return FALSE;
                                }
                        }
                }
        found_object:
...

Do you agree?

Dave







More information about the Crash-utility mailing list