aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKonstantin Khlebnikov <koct9i@gmail.com>2016-03-17 17:22:08 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-03-17 18:09:34 -0400
commit2d6f45b802af7a15a0e455bcfad4009aa5e7b66b (patch)
tree168ed52e0dd19c10b2178015f66fe2e877e44f19
parent7165092fe5ca70bae722ac6cd78421cfd0eec18d (diff)
radix-tree tests: add regression3 test
After calling radix_tree_iter_retry(), 'slot' will be set to NULL. This can cause radix_tree_next_slot() to dereference the NULL pointer. Add Konstantin Khlebnikov's test to the regression framework. Signed-off-by: Matthew Wilcox <matthew.r.wilcox@intel.com> Reported-by: Konstantin Khlebnikov <koct9i@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--tools/testing/radix-tree/Makefile2
-rw-r--r--tools/testing/radix-tree/linux/kernel.h1
-rw-r--r--tools/testing/radix-tree/main.c1
-rw-r--r--tools/testing/radix-tree/regression.h1
-rw-r--r--tools/testing/radix-tree/regression3.c86
5 files changed, 90 insertions, 1 deletions
diff --git a/tools/testing/radix-tree/Makefile b/tools/testing/radix-tree/Makefile
index e33ac3159b49..604212db9d4b 100644
--- a/tools/testing/radix-tree/Makefile
+++ b/tools/testing/radix-tree/Makefile
@@ -3,7 +3,7 @@ CFLAGS += -I. -g -Wall -D_LGPL_SOURCE
3LDFLAGS += -lpthread -lurcu 3LDFLAGS += -lpthread -lurcu
4TARGETS = main 4TARGETS = main
5OFILES = main.o radix-tree.o linux.o test.o tag_check.o find_next_bit.o \ 5OFILES = main.o radix-tree.o linux.o test.o tag_check.o find_next_bit.o \
6 regression1.o regression2.o 6 regression1.o regression2.o regression3.o
7 7
8targets: $(TARGETS) 8targets: $(TARGETS)
9 9
diff --git a/tools/testing/radix-tree/linux/kernel.h b/tools/testing/radix-tree/linux/kernel.h
index 27d5fe41515a..ae013b0160ac 100644
--- a/tools/testing/radix-tree/linux/kernel.h
+++ b/tools/testing/radix-tree/linux/kernel.h
@@ -13,6 +13,7 @@
13 13
14#define BUG_ON(expr) assert(!(expr)) 14#define BUG_ON(expr) assert(!(expr))
15#define __init 15#define __init
16#define __must_check
16#define panic(expr) 17#define panic(expr)
17#define printk printf 18#define printk printf
18#define __force 19#define __force
diff --git a/tools/testing/radix-tree/main.c b/tools/testing/radix-tree/main.c
index 6b8a412c6a11..0e83cad27a9f 100644
--- a/tools/testing/radix-tree/main.c
+++ b/tools/testing/radix-tree/main.c
@@ -261,6 +261,7 @@ int main(void)
261 261
262 regression1_test(); 262 regression1_test();
263 regression2_test(); 263 regression2_test();
264 regression3_test();
264 single_thread_tests(); 265 single_thread_tests();
265 266
266 sleep(1); 267 sleep(1);
diff --git a/tools/testing/radix-tree/regression.h b/tools/testing/radix-tree/regression.h
index bb1c2ab1ae80..e018c4816688 100644
--- a/tools/testing/radix-tree/regression.h
+++ b/tools/testing/radix-tree/regression.h
@@ -3,5 +3,6 @@
3 3
4void regression1_test(void); 4void regression1_test(void);
5void regression2_test(void); 5void regression2_test(void);
6void regression3_test(void);
6 7
7#endif 8#endif
diff --git a/tools/testing/radix-tree/regression3.c b/tools/testing/radix-tree/regression3.c
new file mode 100644
index 000000000000..17d3ba5f4a0a
--- /dev/null
+++ b/tools/testing/radix-tree/regression3.c
@@ -0,0 +1,86 @@
1/*
2 * Regression3
3 * Description:
4 * Helper radix_tree_iter_retry resets next_index to the current index.
5 * In following radix_tree_next_slot current chunk size becomes zero.
6 * This isn't checked and it tries to dereference null pointer in slot.
7 *
8 * Running:
9 * This test should run to completion immediately. The above bug would
10 * cause it to segfault.
11 *
12 * Upstream commit:
13 * Not yet
14 */
15#include <linux/kernel.h>
16#include <linux/gfp.h>
17#include <linux/slab.h>
18#include <linux/radix-tree.h>
19#include <stdlib.h>
20#include <stdio.h>
21
22#include "regression.h"
23
24void regression3_test(void)
25{
26 RADIX_TREE(root, GFP_KERNEL);
27 void *ptr = (void *)4ul;
28 struct radix_tree_iter iter;
29 void **slot;
30 bool first;
31
32 printf("running regression test 3 (should take milliseconds)\n");
33
34 radix_tree_insert(&root, 0, ptr);
35 radix_tree_tag_set(&root, 0, 0);
36
37 first = true;
38 radix_tree_for_each_tagged(slot, &root, &iter, 0, 0) {
39// printk("tagged %ld %p\n", iter.index, *slot);
40 if (first) {
41 radix_tree_insert(&root, 1, ptr);
42 radix_tree_tag_set(&root, 1, 0);
43 first = false;
44 }
45 if (radix_tree_deref_retry(*slot)) {
46// printk("retry %ld\n", iter.index);
47 slot = radix_tree_iter_retry(&iter);
48 continue;
49 }
50 }
51 radix_tree_delete(&root, 1);
52
53 first = true;
54 radix_tree_for_each_slot(slot, &root, &iter, 0) {
55// printk("slot %ld %p\n", iter.index, *slot);
56 if (first) {
57 radix_tree_insert(&root, 1, ptr);
58 first = false;
59 }
60 if (radix_tree_deref_retry(*slot)) {
61// printk("retry %ld\n", iter.index);
62 slot = radix_tree_iter_retry(&iter);
63 continue;
64 }
65 }
66 radix_tree_delete(&root, 1);
67
68 first = true;
69 radix_tree_for_each_contig(slot, &root, &iter, 0) {
70// printk("contig %ld %p\n", iter.index, *slot);
71 if (first) {
72 radix_tree_insert(&root, 1, ptr);
73 first = false;
74 }
75 if (radix_tree_deref_retry(*slot)) {
76// printk("retry %ld\n", iter.index);
77 slot = radix_tree_iter_retry(&iter);
78 continue;
79 }
80 }
81
82 radix_tree_delete(&root, 0);
83 radix_tree_delete(&root, 1);
84
85 printf("regression test 3 passed\n");
86}