I am not sure if this is the right thing to do .... I suspect there may be people on both side of the issue. SLUB places its free pointer in the first word of an object. There it is very vulnerable since write after frees usually occur to the first word. If objects are tighly packed then the writes after the object boundary will also immediately hit free pointer. A corrupted free pointer typically leads to a deferencing of a pointer to nowhere and the system will stop with a bad pointer dereference. While this is good for development (we catch lots of cases that would otherwise corrupt slab objects) it is desirable for stable releases that SLUB behaves more like SLAB: Tolerate object corruption in order to let the system continue its work. This patch produces that type of SLAB behavior in SLUB for CONFIG_STABLE by moving the free pointer to the second word of the object. The first word can then be overwritten and the SLUB will continue without noticing (unless we boot with slub_debug). Signed-off-by: Christoph Lameter --- mm/slub.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) Index: slub/mm/slub.c =================================================================== --- slub.orig/mm/slub.c 2007-05-30 16:40:40.000000000 -0700 +++ slub/mm/slub.c 2007-05-30 16:41:57.000000000 -0700 @@ -374,7 +374,7 @@ static struct track *get_track(struct km { struct track *p; - if (s->offset) + if (s->offset > s->objsize) p = object + s->offset + sizeof(void *); else p = object + s->inuse; @@ -387,7 +387,7 @@ static void set_track(struct kmem_cache { struct track *p; - if (s->offset) + if (s->offset > s->objsize) p = object + s->offset + sizeof(void *); else p = object + s->inuse; @@ -484,7 +484,7 @@ static void print_trailer(struct kmem_ca print_section("Redzone", p + s->objsize, s->inuse - s->objsize); - if (s->offset) + if (s->offset > s->objsize) off = s->offset + sizeof(void *); else off = s->inuse; @@ -618,7 +618,7 @@ static int check_pad_bytes(struct kmem_c { unsigned long off = s->inuse; /* The end of info */ - if (s->offset) + if (s->offset > s->objsize) /* Freepointer is placed after the object. */ off += sizeof(void *); @@ -696,7 +696,7 @@ static int check_object(struct kmem_cach check_pad_bytes(s, page, p); } - if (!s->offset && active) + if (s->offset < s->objsize && active) /* * Object and freepointer overlap. Cannot check * freepointer while object is allocated. @@ -1947,6 +1947,25 @@ static int calculate_sizes(struct kmem_c */ size = ALIGN(size, sizeof(void *)); + +#ifdef CONFIG_STABLE + if (size >= 2*sizeof(void *)) { + /* + * For SLUB robustness we use the second word. The first word + * is likely to be corrupted by write after the object end or + * write after free. This means we do not fail because of + * a corrupted free pointer. We continue with the corrupted + * object like SLAB. + */ + s->offset = sizeof(void *); + } else +#endif + /* + * Object is too small to push back the free pointer a word. Or this is + * not a release kernel. We prefer failures over object corruption. + */ + s->offset = 0; + #ifdef CONFIG_SLUB_DEBUG /* * If we are Redzoning then check if there is some space between the -- - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/