From 331e4deb6dfdac50d3f9c4ccbc41b1427335e212 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Fri, 15 Jan 2016 16:58:53 -0800 Subject: [PATCH] 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 Acked-by: Kees Cook Cc: Al Viro Cc: Andy Shevchenko Cc: Ingo Molnar Cc: Joe Perches Cc: Maurizio Lombardi Cc: Tejun Heo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/test_printf.c | 24 +++++++++++++++++++----- 1 file 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 @@ #include #define BUF_SIZE 256 +#define PAD_SIZE 16 #define FILL_CHAR '$' #define PTR1 ((void*)0x01234567) @@ -39,6 +40,7 @@ static unsigned total_tests __initdata; static unsigned failed_tests __initdata; static char *test_buffer __initdata; +static char *alloced_buffer __initdata; static int __printf(4, 0) __init do_test(int bufsize, const char *expect, int elen, @@ -49,7 +51,7 @@ do_test(int bufsize, const char *expect, int elen, total_tests++; - memset(test_buffer, FILL_CHAR, BUF_SIZE); + memset(alloced_buffer, FILL_CHAR, BUF_SIZE + 2*PAD_SIZE); va_copy(aq, ap); ret = vsnprintf(test_buffer, bufsize, fmt, aq); va_end(aq); @@ -60,8 +62,13 @@ do_test(int bufsize, const char *expect, int elen, return 1; } + if (memchr_inv(alloced_buffer, FILL_CHAR, PAD_SIZE)) { + pr_warn("vsnprintf(buf, %d, \"%s\", ...) wrote before buffer\n", bufsize, fmt); + return 1; + } + if (!bufsize) { - if (memchr_inv(test_buffer, FILL_CHAR, BUF_SIZE)) { + if (memchr_inv(test_buffer, FILL_CHAR, BUF_SIZE + PAD_SIZE)) { pr_warn("vsnprintf(buf, 0, \"%s\", ...) wrote to buffer\n", fmt); return 1; @@ -76,6 +83,12 @@ do_test(int bufsize, const char *expect, int elen, return 1; } + if (memchr_inv(test_buffer + written + 1, FILL_CHAR, BUF_SIZE + PAD_SIZE - (written + 1))) { + pr_warn("vsnprintf(buf, %d, \"%s\", ...) wrote beyond the nul-terminator\n", + bufsize, fmt); + return 1; + } + if (memcmp(test_buffer, expect, written)) { pr_warn("vsnprintf(buf, %d, \"%s\", ...) wrote '%s', expected '%.*s'\n", bufsize, fmt, test_buffer, written, expect); @@ -342,16 +355,17 @@ test_pointer(void) static int __init test_printf_init(void) { - test_buffer = kmalloc(BUF_SIZE, GFP_KERNEL); - if (!test_buffer) + alloced_buffer = kmalloc(BUF_SIZE + 2*PAD_SIZE, GFP_KERNEL); + if (!alloced_buffer) return -ENOMEM; + test_buffer = alloced_buffer + PAD_SIZE; test_basic(); test_number(); test_string(); test_pointer(); - kfree(test_buffer); + kfree(alloced_buffer); if (failed_tests == 0) pr_info("all %u tests passed\n", total_tests);