• I
    [PATCH] slab.c: fix offslab_limit bug · b1ab41c4
    Ingo Molnar 提交于
    mm/slab.c's offlab_limit logic is totally broken.
    
    Firstly, "offslab_limit" is a global variable while it should either be
    calculated in situ or should be passed in as a parameter.
    
    Secondly, the more serious problem with it is that the condition for
    calculating it:
    
                   if (!(OFF_SLAB(sizes->cs_cachep))) {
                           offslab_limit = sizes->cs_size - sizeof(struct slab);
                           offslab_limit /= sizeof(kmem_bufctl_t);
    
    is in total disconnect with the condition that makes use of it:
    
                   /* More than offslab_limit objects will cause problems */
                   if ((flags & CFLGS_OFF_SLAB) && num > offslab_limit)
                           break;
    
    but due to offslab_limit being a global variable this breakage was
    hidden.
    
    Up until lockdep came along and perturbed the slab sizes sufficiently so
    that the first off-slab cache would still see a (non-calculated) zero
    value for offslab_limit and would panic with:
    
      kmem_cache_create: couldn't create cache size-512.
    
      Call Trace:
       [<ffffffff8020a5b9>] show_trace+0x96/0x1c8
       [<ffffffff8020a8f0>] dump_stack+0x13/0x15
       [<ffffffff8022994f>] panic+0x39/0x21a
       [<ffffffff80270814>] kmem_cache_create+0x5a0/0x5d0
       [<ffffffff80aced62>] kmem_cache_init+0x193/0x379
       [<ffffffff80abf779>] start_kernel+0x17f/0x218
       [<ffffffff80abf263>] _sinittext+0x263/0x26a
    
      Kernel panic - not syncing: kmem_cache_create(): failed to create slab `size-512'
    
    Paolo Ornati's config on x86_64 managed to trigger it.
    
    The fix is to move the calculation to the place that makes use of it.
    This also makes slab.o 54 bytes smaller.
    
    Btw., the check itself is quite silly. Its intention is to test whether
    the number of objects per slab would be higher than the number of slab
    control pointers possible. In theory it could be triggered: if someone
    tried to allocate 4-byte objects cache and explicitly requested with
    CFLGS_OFF_SLAB. So i kept the check.
    
    Out of historic interest i checked how old this bug was and it's
    ancient, 10 years old! It is the oldest hidden and then truly triggering
    bugs i ever saw being fixed in the kernel!
    Signed-off-by: NIngo Molnar <mingo@elte.hu>
    Signed-off-by: NLinus Torvalds <torvalds@osdl.org>
    b1ab41c4
slab.c 107.7 KB