original_kernel/lib
Imre Deak 2dcb22b346 idr: fix backtrack logic in idr_remove_all
Currently idr_remove_all will fail with a use after free error if
idr::layers is bigger than 2, which on 32 bit systems corresponds to items
more than 1024.  This is due to stepping back too many levels during
backtracking.  For simplicity let's assume that IDR_BITS=1 -> we have 2
nodes at each level below the root node and each leaf node stores two IDs.
 (In reality for 32 bit systems IDR_BITS=5, with 32 nodes at each sub-root
level and 32 IDs in each leaf node).  The sequence of freeing the nodes at
the moment is as follows:

layer
1 ->                       a(7)
2 ->            b(3)                  c(5)
3 ->        d(1)   e(2)           f(4)    g(6)

Until step 4 things go fine, but then node c is freed, whereas node g
should be freed first.  Since node c contains the pointer to node g we'll
have a use after free error at step 6.

How many levels we step back after visiting the leaf nodes is currently
determined by the msb of the id we are currently visiting:

Step
1.          node d with IDs 0,1 is freed, current ID is advanced to 2.
            msb of the current ID bit 1. This means we need to step back
            1 level to node b and take the next sibling, node e.
2-3.        node e with IDs 2,3 is freed, current ID is 4, msb is bit 2.
            This means we need to step back 2 levels to node a, freeing
            node b on the way.
4-5.        node f with IDs 4,5 is freed, current ID is 6, msb is still
            bit 2. This means we again need to step back 2 levels to node
            a and free c on the way.
6.          We should visit node g, but its pointer is not available as
            node c was freed.

The fix changes how we determine the number of levels to step back.
Instead of deducting this merely from the msb of the current ID, we should
really check if advancing the ID causes an overflow to a bit position
corresponding to a given layer.  In the above example overflow from bit 0
to bit 1 should mean stepping back 1 level.  Overflow from bit 1 to bit 2
should mean stepping back 2 levels and so on.

The fix was tested with IDs up to 1 << 20, which corresponds to 4 layers
on 32 bit systems.

Signed-off-by: Imre Deak <imre.deak@nokia.com>
Reviewed-by: Tejun Heo <tj@kernel.org>
Cc: Eric Paris <eparis@redhat.com>
Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Cc: <stable@kernel.org>		[2.6.34.1]
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-05-27 09:12:48 -07:00
..
lzo
reed_solomon
zlib_deflate
zlib_inflate
.gitignore
Kconfig
Kconfig.debug fault-injection: add CPU notifier error injection module 2010-05-27 09:12:48 -07:00
Kconfig.kgdb
Kconfig.kmemcheck
Makefile fault-injection: add CPU notifier error injection module 2010-05-27 09:12:48 -07:00
argv_split.c
atomic64.c
atomic64_test.c
audit.c
bcd.c
bitmap.c cpusets: randomize node rotor used in cpuset_mem_spread_node() 2010-05-27 09:12:44 -07:00
bitrev.c
btree.c
bug.c
bust_spinlocks.c
check_signature.c
checksum.c
cmdline.c
cpu-notifier-error-inject.c fault-injection: add CPU notifier error injection module 2010-05-27 09:12:48 -07:00
cpumask.c
crc-ccitt.c
crc-itu-t.c
crc-t10dif.c
crc7.c
crc16.c
crc32.c revert "crc32: use __BYTE_ORDER macro for endian detection" 2010-05-26 08:19:23 -07:00
crc32defs.h
ctype.c
debug_locks.c
debugobjects.c
dec_and_lock.c
decompress.c
decompress_bunzip2.c
decompress_inflate.c
decompress_unlzma.c
decompress_unlzo.c
devres.c
div64.c
dma-debug.c
dump_stack.c
dynamic_debug.c dynamic_debug: small cleanup in ddebug_proc_write() 2010-05-25 08:07:05 -07:00
extable.c
fault-inject.c
find_last_bit.c
find_next_bit.c
flex_array.c
gcd.c
gen_crc32table.c crc32: major optimization 2010-05-25 08:07:06 -07:00
genalloc.c
halfmd4.c
hexdump.c lib: introduce common method to convert hex digits 2010-05-25 08:07:05 -07:00
hweight.c
idr.c idr: fix backtrack logic in idr_remove_all 2010-05-27 09:12:48 -07:00
inflate.c
int_sqrt.c
iomap.c
iomap_copy.c
iommu-helper.c
ioremap.c
irq_regs.c
is_single_threaded.c
kasprintf.c
kernel_lock.c
klist.c
kobject.c
kobject_uevent.c hotplug: netns aware uevent_helper 2010-05-21 09:37:33 -07:00
kref.c
lcm.c
libcrc32c.c
list_debug.c
list_sort.c
lmb.c
locking-selftest-hardirq.h
locking-selftest-mutex.h
locking-selftest-rlock-hardirq.h
locking-selftest-rlock-softirq.h
locking-selftest-rlock.h
locking-selftest-rsem.h
locking-selftest-softirq.h
locking-selftest-spin-hardirq.h
locking-selftest-spin-softirq.h
locking-selftest-spin.h
locking-selftest-wlock-hardirq.h
locking-selftest-wlock-softirq.h
locking-selftest-wlock.h
locking-selftest-wsem.h
locking-selftest.c
lru_cache.c
nlattr.c
parser.c
percpu_counter.c
plist.c
prio_heap.c
prio_tree.c
proportions.c
radix-tree.c
random32.c
ratelimit.c
rational.c
rbtree.c
reciprocal_div.c
rwsem-spinlock.c
rwsem.c
scatterlist.c
sha1.c
show_mem.c
smp_processor_id.c
sort.c
spinlock_debug.c
string.c
string_helpers.c
swiotlb.c
syscall.c
textsearch.c
ts_bm.c
ts_fsm.c
ts_kmp.c
vsprintf.c vsprintf.c: use noinline_for_stack 2010-05-25 08:07:04 -07:00