lib/idr.c: fix out-of-bounds pointer dereference 22/32822/2
authorAndrey Ryabinin <a.ryabinin@samsung.com>
Fri, 8 Aug 2014 21:22:07 +0000 (14:22 -0700)
committerChanho Park <chanho61.park@samsung.com>
Mon, 5 Jan 2015 04:50:16 +0000 (20:50 -0800)
commit6bb1b36726e8a9c8232fc2ec70796817b14d8f8e
tree127f77f92ba4ee456b3031e7ee53ffb51de23dda
parent942d62204e43fa8280f702e4bed9f65aa3cde745
lib/idr.c: fix out-of-bounds pointer dereference

I'm working on address sanitizer project for kernel.  Recently we
started experiments with stack instrumentation, to detect out-of-bounds
read/write bugs on stack.

Just after booting I've hit out-of-bounds read on stack in idr_for_each
(and in __idr_remove_all as well):

struct idr_layer **paa = &pa[0];

while (id >= 0 && id <= max) {
...
while (n < fls(id)) {
n += IDR_BITS;
p = *--paa; <--- here we are reading pa[-1] value.
}
}

Despite the fact that after this dereference we are exiting out of loop
and never use p, such behaviour is undefined and should be avoided.

Fix this by moving pointer derference to the beggining of the loop,
right before we will use it.

Signed-off-by: Andrey Ryabinin <a.ryabinin@samsung.com>
Reviewed-by: Lai Jiangshan <laijs@cn.fujitsu.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Alexey Preobrazhensky <preobr@google.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: Konstantin Khlebnikov <koct9i@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Change-Id: Id151fc7e874e3cff64da43eb3359f022de7e6cae
Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
lib/idr.c