diff options
author | Rasmus Villemoes <linux@rasmusvillemoes.dk> | 2016-01-15 19:58:53 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-16 14:17:28 -0500 |
commit | 331e4deb6dfdac50d3f9c4ccbc41b1427335e212 (patch) | |
tree | 3a755146ef906973c041b7c3db2697852e4749f3 /lib/test_printf.c | |
parent | fd0515d50ff33865d0f8cdd74510e8bd1aee88ac (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.c | 24 |
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 @@ | |||
39 | static unsigned total_tests __initdata; | 40 | static unsigned total_tests __initdata; |
40 | static unsigned failed_tests __initdata; | 41 | static unsigned failed_tests __initdata; |
41 | static char *test_buffer __initdata; | 42 | static char *test_buffer __initdata; |
43 | static char *alloced_buffer __initdata; | ||
42 | 44 | ||
43 | static int __printf(4, 0) __init | 45 | static int __printf(4, 0) __init |
44 | do_test(int bufsize, const char *expect, int elen, | 46 | do_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) | |||
342 | static int __init | 355 | static int __init |
343 | test_printf_init(void) | 356 | test_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); |