aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoonsoo Kim <iamjoonsoo.kim@lge.com>2016-07-14 15:07:17 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-07-15 01:54:27 -0400
commit0ab686d8c8303069e80300663b3be6201a8697fb (patch)
tree6dbd0663ea51debd295f0d24b656c82fdfc29497
parent12cb22bb8ae9aff9d72a9c0a234f26d641b20eb6 (diff)
kasan/quarantine: fix bugs on qlist_move_cache()
There are two bugs on qlist_move_cache(). One is that qlist's tail isn't set properly. curr->next can be NULL since it is singly linked list and NULL value on tail is invalid if there is one item on qlist. Another one is that if cache is matched, qlist_put() is called and it will set curr->next to NULL. It would cause to stop the loop prematurely. These problems come from complicated implementation so I'd like to re-implement it completely. Implementation in this patch is really simple. Iterate all qlist_nodes and put them to appropriate list. Unfortunately, I got this bug sometime ago and lose oops message. But, the bug looks trivial and no need to attach oops. Fixes: 55834c59098d ("mm: kasan: initial memory quarantine implementation") Link: http://lkml.kernel.org/r/1467766348-22419-1-git-send-email-iamjoonsoo.kim@lge.com Signed-off-by: Joonsoo Kim <iamjoonsoo.kim@lge.com> Reviewed-by: Dmitry Vyukov <dvyukov@google.com> Acked-by: Andrey Ryabinin <aryabinin@virtuozzo.com> Acked-by: Alexander Potapenko <glider@google.com> Cc: Kuthonuzo Luruo <poll.stdin@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--mm/kasan/quarantine.c29
1 files changed, 11 insertions, 18 deletions
diff --git a/mm/kasan/quarantine.c b/mm/kasan/quarantine.c
index 4973505a9bdd..65793f150d1f 100644
--- a/mm/kasan/quarantine.c
+++ b/mm/kasan/quarantine.c
@@ -238,30 +238,23 @@ static void qlist_move_cache(struct qlist_head *from,
238 struct qlist_head *to, 238 struct qlist_head *to,
239 struct kmem_cache *cache) 239 struct kmem_cache *cache)
240{ 240{
241 struct qlist_node *prev = NULL, *curr; 241 struct qlist_node *curr;
242 242
243 if (unlikely(qlist_empty(from))) 243 if (unlikely(qlist_empty(from)))
244 return; 244 return;
245 245
246 curr = from->head; 246 curr = from->head;
247 qlist_init(from);
247 while (curr) { 248 while (curr) {
248 struct qlist_node *qlink = curr; 249 struct qlist_node *next = curr->next;
249 struct kmem_cache *obj_cache = qlink_to_cache(qlink); 250 struct kmem_cache *obj_cache = qlink_to_cache(curr);
250 251
251 if (obj_cache == cache) { 252 if (obj_cache == cache)
252 if (unlikely(from->head == qlink)) { 253 qlist_put(to, curr, obj_cache->size);
253 from->head = curr->next; 254 else
254 prev = curr; 255 qlist_put(from, curr, obj_cache->size);
255 } else 256
256 prev->next = curr->next; 257 curr = next;
257 if (unlikely(from->tail == qlink))
258 from->tail = curr->next;
259 from->bytes -= cache->size;
260 qlist_put(to, qlink, cache->size);
261 } else {
262 prev = curr;
263 }
264 curr = curr->next;
265 } 258 }
266} 259}
267 260