• Lai Jiangshan's avatar
    idr: fix unexpected ID-removal when idr_remove(unallocated_id) · 8f9f665a
    Lai Jiangshan authored
    If unallocated_id = (ANY * idr_max(idp->layers) + existing_id) is passed
    to idr_remove().  The existing_id will be removed unexpectedly.
    
    The following test shows this unexpected id-removal:
    
      static void test4(void)
      {
            int id;
            DEFINE_IDR(test_idr);
    
            printk(KERN_INFO "Start test4\n");
            id = idr_alloc(&test_idr, (void *)1, 42, 43, GFP_KERNEL);
            BUG_ON(id != 42);
            idr_remove(&test_idr, 42 + IDR_SIZE);
            TEST_BUG_ON(idr_find(&test_idr, 42) != (void *)1);
            idr_destroy(&test_idr);
            printk(KERN_INFO "End of test4\n");
      }
    
    ida_remove() shares the similar problem.
    
    It happens only when the caller tries to free an unallocated ID which is
    the caller's fault.  It is not a bug.  But it is better to add the
    proper check and complain rather than removing an existing_id silently.
    Signed-off-by: default avatarLai Jiangshan <laijs@cn.fujitsu.com>
    Acked-by: default avatarTejun Heo <tj@kernel.org>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    8f9f665a
idr.c 28.6 KB