aboutsummaryrefslogtreecommitdiffstats
path: root/lib/test_printf.c
diff options
context:
space:
mode:
authorRasmus Villemoes <linux@rasmusvillemoes.dk>2016-01-15 19:58:53 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-01-16 14:17:28 -0500
commit331e4deb6dfdac50d3f9c4ccbc41b1427335e212 (patch)
tree3a755146ef906973c041b7c3db2697852e4749f3 /lib/test_printf.c
parentfd0515d50ff33865d0f8cdd74510e8bd1aee88ac (diff)
lib/test_printf.c: check for out-of-bound writes
Add a few padding bytes on either side of the test buffer, and check that these (and the part of the buffer not used) are untouched by vsnprintf. Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk> Acked-by: Kees Cook <keescook@chromium.org> Cc: Al Viro <viro@ZenIV.linux.org.uk> Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Joe Perches <joe@perches.com> Cc: Maurizio Lombardi <mlombard@redhat.com> Cc: Tejun Heo <tj@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'lib/test_printf.c')
-rw-r--r--lib/test_printf.c24
1 files changed, 19 insertions, 5 deletions
diff --git a/lib/test_printf.c b/lib/test_printf.c
index 9232a2add28c..1ce1a1dd8faf 100644
--- a/lib/test_printf.c
+++ b/lib/test_printf.c
@@ -16,6 +16,7 @@
16#include <linux/in.h> 16#include <linux/in.h>
17 17
18#define BUF_SIZE 256 18#define BUF_SIZE 256
19#define PAD_SIZE 16
19#define FILL_CHAR '$' 20#define FILL_CHAR '$'
20 21
21#define PTR1 ((void*)0x01234567) 22#define PTR1 ((void*)0x01234567)
@@ -39,6 +40,7 @@
39static unsigned total_tests __initdata; 40static unsigned total_tests __initdata;
40static unsigned failed_tests __initdata; 41static unsigned failed_tests __initdata;
41static char *test_buffer __initdata; 42static char *test_buffer __initdata;
43static char *alloced_buffer __initdata;
42 44
43static int __printf(4, 0) __init 45static int __printf(4, 0) __init
44do_test(int bufsize, const char *expect, int elen, 46do_test(int bufsize, const char *expect, int elen,
@@ -49,7 +51,7 @@ do_test(int bufsize, const char *expect, int elen,
49 51
50 total_tests++; 52 total_tests++;
51 53
52 memset(test_buffer, FILL_CHAR, BUF_SIZE); 54 memset(alloced_buffer, FILL_CHAR, BUF_SIZE + 2*PAD_SIZE);
53 va_copy(aq, ap); 55 va_copy(aq, ap);
54 ret = vsnprintf(test_buffer, bufsize, fmt, aq); 56 ret = vsnprintf(test_buffer, bufsize, fmt, aq);
55 va_end(aq); 57 va_end(aq);
@@ -60,8 +62,13 @@ do_test(int bufsize, const char *expect, int elen,
60 return 1; 62 return 1;
61 } 63 }
62 64
65 if (memchr_inv(alloced_buffer, FILL_CHAR, PAD_SIZE)) {
66 pr_warn("vsnprintf(buf, %d, \"%s\", ...) wrote before buffer\n", bufsize, fmt);
67 return 1;
68 }
69
63 if (!bufsize) { 70 if (!bufsize) {
64 if (memchr_inv(test_buffer, FILL_CHAR, BUF_SIZE)) { 71 if (memchr_inv(test_buffer, FILL_CHAR, BUF_SIZE + PAD_SIZE)) {
65 pr_warn("vsnprintf(buf, 0, \"%s\", ...) wrote to buffer\n", 72 pr_warn("vsnprintf(buf, 0, \"%s\", ...) wrote to buffer\n",
66 fmt); 73 fmt);
67 return 1; 74 return 1;
@@ -76,6 +83,12 @@ do_test(int bufsize, const char *expect, int elen,
76 return 1; 83 return 1;
77 } 84 }
78 85
86 if (memchr_inv(test_buffer + written + 1, FILL_CHAR, BUF_SIZE + PAD_SIZE - (written + 1))) {
87 pr_warn("vsnprintf(buf, %d, \"%s\", ...) wrote beyond the nul-terminator\n",
88 bufsize, fmt);
89 return 1;
90 }
91
79 if (memcmp(test_buffer, expect, written)) { 92 if (memcmp(test_buffer, expect, written)) {
80 pr_warn("vsnprintf(buf, %d, \"%s\", ...) wrote '%s', expected '%.*s'\n", 93 pr_warn("vsnprintf(buf, %d, \"%s\", ...) wrote '%s', expected '%.*s'\n",
81 bufsize, fmt, test_buffer, written, expect); 94 bufsize, fmt, test_buffer, written, expect);
@@ -342,16 +355,17 @@ test_pointer(void)
342static int __init 355static int __init
343test_printf_init(void) 356test_printf_init(void)
344{ 357{
345 test_buffer = kmalloc(BUF_SIZE, GFP_KERNEL); 358 alloced_buffer = kmalloc(BUF_SIZE + 2*PAD_SIZE, GFP_KERNEL);
346 if (!test_buffer) 359 if (!alloced_buffer)
347 return -ENOMEM; 360 return -ENOMEM;
361 test_buffer = alloced_buffer + PAD_SIZE;
348 362
349 test_basic(); 363 test_basic();
350 test_number(); 364 test_number();
351 test_string(); 365 test_string();
352 test_pointer(); 366 test_pointer();
353 367
354 kfree(test_buffer); 368 kfree(alloced_buffer);
355 369
356 if (failed_tests == 0) 370 if (failed_tests == 0)
357 pr_info("all %u tests passed\n", total_tests); 371 pr_info("all %u tests passed\n", total_tests);