| From 6b6a7846a6438a747cfe8f1d0aa0f15a513b47f9 Mon Sep 17 00:00:00 2001 |
| From: Jia He <justin.he@arm.com> |
| Date: Fri, 9 Aug 2019 09:24:56 +0800 |
| Subject: [PATCH] vsprintf: Prevent crash when dereferencing invalid pointers |
| for %pD |
| |
| commit 36594b317c656bec8f968db93701d2cb9bc9155c upstream. |
| |
| 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 <geert+renesas@glider.be> |
| To: Thomas Gleixner <tglx@linutronix.de> |
| To: Andy Shevchenko <andriy.shevchenko@linux.intel.com> |
| To: linux-kernel@vger.kernel.org |
| Cc: Kees Cook <keescook@chromium.org> |
| Cc: "Steven Rostedt (VMware)" <rostedt@goodmis.org> |
| Cc: Shuah Khan <shuah@kernel.org> |
| Cc: "Tobin C. Harding" <tobin@kernel.org> |
| Signed-off-by: Jia He <justin.he@arm.com> |
| Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com> |
| Reviewed-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com> |
| Signed-off-by: Petr Mladek <pmladek@suse.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/lib/vsprintf.c b/lib/vsprintf.c |
| index 977b9f982b38..672b1817e639 100644 |
| --- a/lib/vsprintf.c |
| +++ b/lib/vsprintf.c |
| @@ -876,6 +876,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, |
| @@ -2173,9 +2182,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); |
| -- |
| 2.27.0 |
| |