From 36594b317c656bec8f968db93701d2cb9bc9155c Mon Sep 17 00:00:00 2001 From: Jia He Date: Fri, 9 Aug 2019 09:24:56 +0800 Subject: vsprintf: Prevent crash when dereferencing invalid pointers for %pD Commit 3e5903eb9cff ("vsprintf: Prevent crash when dereferencing invalid pointers") prevents most crash except for %pD. There is an additional pointer dereferencing before dentry_name. At least, vma->file can be NULL and be passed to printk %pD in print_bad_pte, which can cause crash. This patch fixes it with introducing a new file_dentry_name. Link: http://lkml.kernel.org/r/20190809012457.56685-1-justin.he@arm.com Fixes: 3e5903eb9cff ("vsprintf: Prevent crash when dereferencing invalid pointers") To: Geert Uytterhoeven To: Thomas Gleixner To: Andy Shevchenko To: linux-kernel@vger.kernel.org Cc: Kees Cook Cc: "Steven Rostedt (VMware)" Cc: Shuah Khan Cc: "Tobin C. Harding" Signed-off-by: Jia He Reviewed-by: Andy Shevchenko Reviewed-by: Sergey Senozhatsky Signed-off-by: Petr Mladek --- lib/vsprintf.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/vsprintf.c b/lib/vsprintf.c index b0967cf17137..e78017a3e1bd 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -869,6 +869,15 @@ char *dentry_name(char *buf, char *end, const struct dentry *d, struct printf_sp return widen_string(buf, n, end, spec); } +static noinline_for_stack +char *file_dentry_name(char *buf, char *end, const struct file *f, + struct printf_spec spec, const char *fmt) +{ + if (check_pointer(&buf, end, f, spec)) + return buf; + + return dentry_name(buf, end, f->f_path.dentry, spec, fmt); +} #ifdef CONFIG_BLOCK static noinline_for_stack char *bdev_name(char *buf, char *end, struct block_device *bdev, @@ -2166,9 +2175,7 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, case 'C': return clock(buf, end, ptr, spec, fmt); case 'D': - return dentry_name(buf, end, - ((const struct file *)ptr)->f_path.dentry, - spec, fmt); + return file_dentry_name(buf, end, ptr, spec, fmt); #ifdef CONFIG_BLOCK case 'g': return bdev_name(buf, end, ptr, spec, fmt); -- cgit v1.2.3-59-g8ed1b From cf6b7921fc19e537cd5ae88460195c8599eb5d9d Mon Sep 17 00:00:00 2001 From: Jia He Date: Fri, 9 Aug 2019 09:24:57 +0800 Subject: lib/test_printf: Add test of null/invalid pointer dereference for dentry This add some additional test cases of null/invalid pointer dereference for dentry and file (%pd and %pD) Link: http://lkml.kernel.org/r/20190809012457.56685-2-justin.he@arm.com To: Geert Uytterhoeven To: Sergey Senozhatsky To: Thomas Gleixner To: Andy Shevchenko To: Petr Mladek To: linux-kernel@vger.kernel.org Cc: Kees Cook Cc: "Steven Rostedt (VMware)" Cc: Shuah Khan Cc: "Tobin C. Harding" Signed-off-by: Jia He Reviewed-by: Andy Shevchenko Reviewed-by: Sergey Senozhatsky Signed-off-by: Petr Mladek --- lib/test_printf.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'lib') diff --git a/lib/test_printf.c b/lib/test_printf.c index 944eb50f3862..befedffeb476 100644 --- a/lib/test_printf.c +++ b/lib/test_printf.c @@ -455,6 +455,13 @@ dentry(void) test("foo", "%pd", &test_dentry[0]); test("foo", "%pd2", &test_dentry[0]); + /* test the null/invalid pointer case for dentry */ + test("(null)", "%pd", NULL); + test("(efault)", "%pd", PTR_INVALID); + /* test the null/invalid pointer case for file */ + test("(null)", "%pD", NULL); + test("(efault)", "%pD", PTR_INVALID); + test("romeo", "%pd", &test_dentry[3]); test("alfa/romeo", "%pd2", &test_dentry[3]); test("bravo/alfa/romeo", "%pd3", &test_dentry[3]); -- cgit v1.2.3-59-g8ed1b From 8ebea6ea1a7ed5d67ecbb2a493c716a2a89c0be2 Mon Sep 17 00:00:00 2001 From: Petr Mladek Date: Thu, 15 Aug 2019 17:01:33 +0200 Subject: lib/test_printf: Remove obvious comments from %pd and %pD tests Signed-off-by: Petr Mladek --- lib/test_printf.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'lib') diff --git a/lib/test_printf.c b/lib/test_printf.c index befedffeb476..5d94cbff2120 100644 --- a/lib/test_printf.c +++ b/lib/test_printf.c @@ -455,10 +455,8 @@ dentry(void) test("foo", "%pd", &test_dentry[0]); test("foo", "%pd2", &test_dentry[0]); - /* test the null/invalid pointer case for dentry */ test("(null)", "%pd", NULL); test("(efault)", "%pd", PTR_INVALID); - /* test the null/invalid pointer case for file */ test("(null)", "%pD", NULL); test("(efault)", "%pD", PTR_INVALID); -- cgit v1.2.3-59-g8ed1b