Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP5:Update
crash.1433
crash-kmem_cache-downsize.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File crash-kmem_cache-downsize.patch of Package crash.1433
From: Dave Anderson <anderson@redhat.com> Date: Thu Feb 20 15:36:25 2014 -0500 Subject: Fix kmem slab initialization failures References: bnc#885082 Patch-mainline: v6.0.6 Git-commit: c0b7a74fc13121203810d06d163550436b2d5476 Fix to prevent a possible invocation-time error on Linux 3.7 and later kernels configured with CONFIG_SLAB, running against vmcore files filtered with the makedumpfile(8) facility. Without the patch, the message "crash: page excluded: kernel virtual address: <address> type: kmem_cache buffer" is immediately followed by the message "crash: unable to initialize kmem slab cache subsystem". Because of a kernel data structure name change from "cache_cache" to "kmem_cache_boot", the crash utility failed to properly downsize the stored size of the kernel's kmem_cache data structure from the size indicated by the vmlinux debuginfo data. This in turn could lead to reading beyond the end of a kmem_cache data structure into a page of memory that had been excluded from the vmcore. The fix was also applied to kernels configured with CONFIG_SLUB. (anderson@redhat.com) Acked-by: Petr Tesarik <ptesarik@suse.cz> diff --git a/memory.c b/memory.c index 17e5d1c..01c5ffe 100644 --- a/memory.c +++ b/memory.c @@ -8677,13 +8677,32 @@ static void kmem_cache_downsize(void) { char *cache_buf; - uint buffer_size; + ulong kmem_cache; + uint buffer_size, object_size; int nr_node_ids; int nr_cpu_ids; + if (vt->flags & KMALLOC_SLUB) { + if (kernel_symbol_exists("kmem_cache") && + VALID_MEMBER(kmem_cache_objsize) && + try_get_symbol_data("kmem_cache", + sizeof(ulong), &kmem_cache) && + readmem(kmem_cache + OFFSET(kmem_cache_objsize), + KVADDR, &object_size, sizeof(int), + "kmem_cache objsize/object_size", RETURN_ON_ERROR)) { + ASSIGN_SIZE(kmem_cache) = object_size; + if (CRASHDEBUG(1)) + fprintf(fp, "\nkmem_cache_downsize: %ld to %ld\n", + STRUCT_SIZE("kmem_cache"), + SIZE(kmem_cache)); + } + return; + } + if ((THIS_KERNEL_VERSION < LINUX(2,6,22)) || !(vt->flags & PERCPU_KMALLOC_V2_NODES) || - !kernel_symbol_exists("cache_cache") || + (!kernel_symbol_exists("cache_cache") && + !kernel_symbol_exists("kmem_cache_boot")) || (!MEMBER_EXISTS("kmem_cache", "buffer_size") && !MEMBER_EXISTS("kmem_cache", "size"))) { return; @@ -8691,7 +8710,28 @@ kmem_cache_downsize(void) if (vt->flags & NODELISTS_IS_PTR) { /* - * kmem_cache.array[] is actually sized by + * More recent kernels have kmem_cache.array[] sized + * by the number of cpus plus the number of nodes. + */ + if (kernel_symbol_exists("kmem_cache_boot") && + MEMBER_EXISTS("kmem_cache", "object_size") && + readmem(symbol_value("kmem_cache_boot") + + MEMBER_OFFSET("kmem_cache", "object_size"), + KVADDR, &object_size, sizeof(int), + "kmem_cache_boot object_size", RETURN_ON_ERROR)) + ASSIGN_SIZE(kmem_cache_s) = object_size; + else if (kernel_symbol_exists("cache_cache") && + MEMBER_EXISTS("kmem_cache", "object_size") && + readmem(symbol_value("cache_cache") + + MEMBER_OFFSET("kmem_cache", "object_size"), + KVADDR, &object_size, sizeof(int), + "cache_cache object_size", RETURN_ON_ERROR)) + ASSIGN_SIZE(kmem_cache_s) = object_size; + else + object_size = 0; + + /* + * Older kernels have kmem_cache.array[] sized by * the number of cpus; real value is nr_cpu_ids, * but fallback is kt->cpus. */ @@ -8702,10 +8742,12 @@ kmem_cache_downsize(void) nr_cpu_ids = kt->cpus; ARRAY_LENGTH(kmem_cache_s_array) = nr_cpu_ids; - ASSIGN_SIZE(kmem_cache_s) = OFFSET(kmem_cache_s_array) + - sizeof(ulong) * nr_cpu_ids; + + if (!object_size) + ASSIGN_SIZE(kmem_cache_s) = OFFSET(kmem_cache_s_array) + + sizeof(ulong) * nr_cpu_ids; if (CRASHDEBUG(1)) - fprintf(fp, "kmem_cache_downsize: %ld to %ld\n", + fprintf(fp, "\nkmem_cache_downsize: %ld to %ld\n", STRUCT_SIZE("kmem_cache"), SIZE(kmem_cache_s)); return; } @@ -8713,7 +8755,7 @@ kmem_cache_downsize(void) cache_buf = GETBUF(SIZE(kmem_cache_s)); if (!readmem(symbol_value("cache_cache"), KVADDR, cache_buf, - SIZE(kmem_cache_s), "kmem_cache buffer", FAULT_ON_ERROR)) { + SIZE(kmem_cache_s), "kmem_cache buffer", RETURN_ON_ERROR)) { FREEBUF(cache_buf); return; } @@ -8741,8 +8783,7 @@ kmem_cache_downsize(void) if (CRASHDEBUG(1)) { fprintf(fp, - "\nkmem_cache_downsize: SIZE(kmem_cache_s): %ld " - "cache_cache.buffer_size: %d\n", + "\nkmem_cache_downsize: %ld to %d\n", STRUCT_SIZE("kmem_cache"), buffer_size); fprintf(fp, "kmem_cache_downsize: nr_node_ids: %ld\n", @@ -16790,6 +16831,8 @@ kmem_cache_init_slub(void) "kmem_cache_init_slub: numnodes: %d without CONFIG_NUMA\n", vt->numnodes); + kmem_cache_downsize(); + vt->cpu_slab_type = MEMBER_TYPE("kmem_cache", "cpu_slab"); vt->flags |= KMEM_CACHE_INIT;
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor