]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 4.4
authorSasha Levin <sashal@kernel.org>
Sat, 1 Aug 2020 21:58:03 +0000 (17:58 -0400)
committerSasha Levin <sashal@kernel.org>
Sat, 1 Aug 2020 21:58:03 +0000 (17:58 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-4.4/arm-8986-1-hw_breakpoint-don-t-invoke-overflow-handl.patch [new file with mode: 0644]
queue-4.4/fbdev-detect-integer-underflow-at-struct-fbcon_ops-c.patch [new file with mode: 0644]
queue-4.4/series
queue-4.4/x86-build-lto-fix-truncated-.bss-with-fdata-sections.patch [new file with mode: 0644]
queue-4.4/x86-vmlinux.lds-page-align-end-of-.page_aligned-sect.patch [new file with mode: 0644]

diff --git a/queue-4.4/arm-8986-1-hw_breakpoint-don-t-invoke-overflow-handl.patch b/queue-4.4/arm-8986-1-hw_breakpoint-don-t-invoke-overflow-handl.patch
new file mode 100644 (file)
index 0000000..b33be7a
--- /dev/null
@@ -0,0 +1,86 @@
+From 41953ab8b82a6b368a29f41136e96573b995600e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 18 Jun 2020 11:16:45 +0100
+Subject: ARM: 8986/1: hw_breakpoint: Don't invoke overflow handler on uaccess
+ watchpoints
+
+From: Will Deacon <will@kernel.org>
+
+[ Upstream commit eec13b42d41b0f3339dcf0c4da43734427c68620 ]
+
+Unprivileged memory accesses generated by the so-called "translated"
+instructions (e.g. LDRT) in kernel mode can cause user watchpoints to fire
+unexpectedly. In such cases, the hw_breakpoint logic will invoke the user
+overflow handler which will typically raise a SIGTRAP back to the current
+task. This is futile when returning back to the kernel because (a) the
+signal won't have been delivered and (b) userspace can't handle the thing
+anyway.
+
+Avoid invoking the user overflow handler for watchpoints triggered by
+kernel uaccess routines, and instead single-step over the faulting
+instruction as we would if no overflow handler had been installed.
+
+Cc: <stable@vger.kernel.org>
+Fixes: f81ef4a920c8 ("ARM: 6356/1: hw-breakpoint: add ARM backend for the hw-breakpoint framework")
+Reported-by: Luis Machado <luis.machado@linaro.org>
+Tested-by: Luis Machado <luis.machado@linaro.org>
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/kernel/hw_breakpoint.c | 27 ++++++++++++++++++++++-----
+ 1 file changed, 22 insertions(+), 5 deletions(-)
+
+diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
+index abcbea1ae30ba..78c6be1b27145 100644
+--- a/arch/arm/kernel/hw_breakpoint.c
++++ b/arch/arm/kernel/hw_breakpoint.c
+@@ -688,6 +688,12 @@ static void disable_single_step(struct perf_event *bp)
+       arch_install_hw_breakpoint(bp);
+ }
++static int watchpoint_fault_on_uaccess(struct pt_regs *regs,
++                                     struct arch_hw_breakpoint *info)
++{
++      return !user_mode(regs) && info->ctrl.privilege == ARM_BREAKPOINT_USER;
++}
++
+ static void watchpoint_handler(unsigned long addr, unsigned int fsr,
+                              struct pt_regs *regs)
+ {
+@@ -747,16 +753,27 @@ static void watchpoint_handler(unsigned long addr, unsigned int fsr,
+               }
+               pr_debug("watchpoint fired: address = 0x%x\n", info->trigger);
++
++              /*
++               * If we triggered a user watchpoint from a uaccess routine,
++               * then handle the stepping ourselves since userspace really
++               * can't help us with this.
++               */
++              if (watchpoint_fault_on_uaccess(regs, info))
++                      goto step;
++
+               perf_bp_event(wp, regs);
+               /*
+-               * If no overflow handler is present, insert a temporary
+-               * mismatch breakpoint so we can single-step over the
+-               * watchpoint trigger.
++               * Defer stepping to the overflow handler if one is installed.
++               * Otherwise, insert a temporary mismatch breakpoint so that
++               * we can single-step over the watchpoint trigger.
+                */
+-              if (!wp->overflow_handler)
+-                      enable_single_step(wp, instruction_pointer(regs));
++              if (wp->overflow_handler)
++                      goto unlock;
++step:
++              enable_single_step(wp, instruction_pointer(regs));
+ unlock:
+               rcu_read_unlock();
+       }
+-- 
+2.25.1
+
diff --git a/queue-4.4/fbdev-detect-integer-underflow-at-struct-fbcon_ops-c.patch b/queue-4.4/fbdev-detect-integer-underflow-at-struct-fbcon_ops-c.patch
new file mode 100644 (file)
index 0000000..37b7814
--- /dev/null
@@ -0,0 +1,157 @@
+From c1cc1807f3c7dff53c23b0d9f9eabefa8818f399 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jul 2020 10:51:02 +0900
+Subject: fbdev: Detect integer underflow at "struct fbcon_ops"->clear_margins.
+
+From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+
+[ Upstream commit 033724d6864245a11f8e04c066002e6ad22b3fd0 ]
+
+syzbot is reporting general protection fault in bitfill_aligned() [1]
+caused by integer underflow in bit_clear_margins(). The cause of this
+problem is when and how do_vc_resize() updates vc->vc_{cols,rows}.
+
+If vc_do_resize() fails (e.g. kzalloc() fails) when var.xres or var.yres
+is going to shrink, vc->vc_{cols,rows} will not be updated. This allows
+bit_clear_margins() to see info->var.xres < (vc->vc_cols * cw) or
+info->var.yres < (vc->vc_rows * ch). Unexpectedly large rw or bh will
+try to overrun the __iomem region and causes general protection fault.
+
+Also, vc_resize(vc, 0, 0) does not set vc->vc_{cols,rows} = 0 due to
+
+  new_cols = (cols ? cols : vc->vc_cols);
+  new_rows = (lines ? lines : vc->vc_rows);
+
+exception. Since cols and lines are calculated as
+
+  cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
+  rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
+  cols /= vc->vc_font.width;
+  rows /= vc->vc_font.height;
+  vc_resize(vc, cols, rows);
+
+in fbcon_modechanged(), var.xres < vc->vc_font.width makes cols = 0
+and var.yres < vc->vc_font.height makes rows = 0. This means that
+
+  const int fd = open("/dev/fb0", O_ACCMODE);
+  struct fb_var_screeninfo var = { };
+  ioctl(fd, FBIOGET_VSCREENINFO, &var);
+  var.xres = var.yres = 1;
+  ioctl(fd, FBIOPUT_VSCREENINFO, &var);
+
+easily reproduces integer underflow bug explained above.
+
+Of course, callers of vc_resize() are not handling vc_do_resize() failure
+is bad. But we can't avoid vc_resize(vc, 0, 0) which returns 0. Therefore,
+as a band-aid workaround, this patch checks integer underflow in
+"struct fbcon_ops"->clear_margins call, assuming that
+vc->vc_cols * vc->vc_font.width and vc->vc_rows * vc->vc_font.heigh do not
+cause integer overflow.
+
+[1] https://syzkaller.appspot.com/bug?id=a565882df74fa76f10d3a6fec4be31098dbb37c6
+
+Reported-and-tested-by: syzbot <syzbot+e5fd3e65515b48c02a30@syzkaller.appspotmail.com>
+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Cc: stable <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20200715015102.3814-1-penguin-kernel@I-love.SAKURA.ne.jp
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/video/console/bitblit.c   | 4 ++--
+ drivers/video/console/fbcon_ccw.c | 4 ++--
+ drivers/video/console/fbcon_cw.c  | 4 ++--
+ drivers/video/console/fbcon_ud.c  | 4 ++--
+ 4 files changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
+index dbfe4eecf12e5..05d1d36a56654 100644
+--- a/drivers/video/console/bitblit.c
++++ b/drivers/video/console/bitblit.c
+@@ -216,7 +216,7 @@ static void bit_clear_margins(struct vc_data *vc, struct fb_info *info,
+       region.color = 0;
+       region.rop = ROP_COPY;
+-      if (rw && !bottom_only) {
++      if ((int) rw > 0 && !bottom_only) {
+               region.dx = info->var.xoffset + rs;
+               region.dy = 0;
+               region.width = rw;
+@@ -224,7 +224,7 @@ static void bit_clear_margins(struct vc_data *vc, struct fb_info *info,
+               info->fbops->fb_fillrect(info, &region);
+       }
+-      if (bh) {
++      if ((int) bh > 0) {
+               region.dx = info->var.xoffset;
+               region.dy = info->var.yoffset + bs;
+               region.width = rs;
+diff --git a/drivers/video/console/fbcon_ccw.c b/drivers/video/console/fbcon_ccw.c
+index 5a3cbf6dff4d9..34da8bba9273a 100644
+--- a/drivers/video/console/fbcon_ccw.c
++++ b/drivers/video/console/fbcon_ccw.c
+@@ -201,7 +201,7 @@ static void ccw_clear_margins(struct vc_data *vc, struct fb_info *info,
+       region.color = 0;
+       region.rop = ROP_COPY;
+-      if (rw && !bottom_only) {
++      if ((int) rw > 0 && !bottom_only) {
+               region.dx = 0;
+               region.dy = info->var.yoffset;
+               region.height = rw;
+@@ -209,7 +209,7 @@ static void ccw_clear_margins(struct vc_data *vc, struct fb_info *info,
+               info->fbops->fb_fillrect(info, &region);
+       }
+-      if (bh) {
++      if ((int) bh > 0) {
+               region.dx = info->var.xoffset + bs;
+               region.dy = 0;
+                 region.height = info->var.yres_virtual;
+diff --git a/drivers/video/console/fbcon_cw.c b/drivers/video/console/fbcon_cw.c
+index e7ee44db4e98b..0b552b3fc22ab 100644
+--- a/drivers/video/console/fbcon_cw.c
++++ b/drivers/video/console/fbcon_cw.c
+@@ -184,7 +184,7 @@ static void cw_clear_margins(struct vc_data *vc, struct fb_info *info,
+       region.color = 0;
+       region.rop = ROP_COPY;
+-      if (rw && !bottom_only) {
++      if ((int) rw > 0 && !bottom_only) {
+               region.dx = 0;
+               region.dy = info->var.yoffset + rs;
+               region.height = rw;
+@@ -192,7 +192,7 @@ static void cw_clear_margins(struct vc_data *vc, struct fb_info *info,
+               info->fbops->fb_fillrect(info, &region);
+       }
+-      if (bh) {
++      if ((int) bh > 0) {
+               region.dx = info->var.xoffset;
+               region.dy = info->var.yoffset;
+                 region.height = info->var.yres;
+diff --git a/drivers/video/console/fbcon_ud.c b/drivers/video/console/fbcon_ud.c
+index 19e3714abfe8f..7f62efe2da526 100644
+--- a/drivers/video/console/fbcon_ud.c
++++ b/drivers/video/console/fbcon_ud.c
+@@ -231,7 +231,7 @@ static void ud_clear_margins(struct vc_data *vc, struct fb_info *info,
+       region.color = 0;
+       region.rop = ROP_COPY;
+-      if (rw && !bottom_only) {
++      if ((int) rw > 0 && !bottom_only) {
+               region.dy = 0;
+               region.dx = info->var.xoffset;
+               region.width  = rw;
+@@ -239,7 +239,7 @@ static void ud_clear_margins(struct vc_data *vc, struct fb_info *info,
+               info->fbops->fb_fillrect(info, &region);
+       }
+-      if (bh) {
++      if ((int) bh > 0) {
+               region.dy = info->var.yoffset;
+               region.dx = info->var.xoffset;
+                 region.height  = bh;
+-- 
+2.25.1
+
index e2240b7f1951bca4c0fe11547b7ce4019e80e57a..4169d437f9c7b02f98f829aecabaf526cb5a2bda 100644 (file)
@@ -12,3 +12,7 @@ drm-hold-gem-reference-until-object-is-no-longer-accessed.patch
 arm-percpu.h-fix-build-error.patch
 f2fs-check-memory-boundary-by-insane-namelen.patch
 f2fs-check-if-file-namelen-exceeds-max-value.patch
+arm-8986-1-hw_breakpoint-don-t-invoke-overflow-handl.patch
+x86-build-lto-fix-truncated-.bss-with-fdata-sections.patch
+x86-vmlinux.lds-page-align-end-of-.page_aligned-sect.patch
+fbdev-detect-integer-underflow-at-struct-fbcon_ops-c.patch
diff --git a/queue-4.4/x86-build-lto-fix-truncated-.bss-with-fdata-sections.patch b/queue-4.4/x86-build-lto-fix-truncated-.bss-with-fdata-sections.patch
new file mode 100644 (file)
index 0000000..ab12d8f
--- /dev/null
@@ -0,0 +1,54 @@
+From 08dfba9cb1d8b35c132726a0ab8adb8785832714 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Apr 2019 09:49:56 -0700
+Subject: x86/build/lto: Fix truncated .bss with -fdata-sections
+
+From: Sami Tolvanen <samitolvanen@google.com>
+
+[ Upstream commit 6a03469a1edc94da52b65478f1e00837add869a3 ]
+
+With CONFIG_LD_DEAD_CODE_DATA_ELIMINATION=y, we compile the kernel with
+-fdata-sections, which also splits the .bss section.
+
+The new section, with a new .bss.* name, which pattern gets missed by the
+main x86 linker script which only expects the '.bss' name. This results
+in the discarding of the second part and a too small, truncated .bss
+section and an unhappy, non-working kernel.
+
+Use the common BSS_MAIN macro in the linker script to properly capture
+and merge all the generated BSS sections.
+
+Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
+Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
+Reviewed-by: Kees Cook <keescook@chromium.org>
+Cc: Borislav Petkov <bp@alien8.de>
+Cc: Kees Cook <keescook@chromium.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Nicholas Piggin <npiggin@gmail.com>
+Cc: Nick Desaulniers <ndesaulniers@google.com>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Link: http://lkml.kernel.org/r/20190415164956.124067-1-samitolvanen@google.com
+[ Extended the changelog. ]
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kernel/vmlinux.lds.S | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
+index b05da220ea0a2..9b185142219b9 100644
+--- a/arch/x86/kernel/vmlinux.lds.S
++++ b/arch/x86/kernel/vmlinux.lds.S
+@@ -330,7 +330,7 @@ SECTIONS
+       .bss : AT(ADDR(.bss) - LOAD_OFFSET) {
+               __bss_start = .;
+               *(.bss..page_aligned)
+-              *(.bss)
++              *(BSS_MAIN)
+               . = ALIGN(PAGE_SIZE);
+               __bss_stop = .;
+       }
+-- 
+2.25.1
+
diff --git a/queue-4.4/x86-vmlinux.lds-page-align-end-of-.page_aligned-sect.patch b/queue-4.4/x86-vmlinux.lds-page-align-end-of-.page_aligned-sect.patch
new file mode 100644 (file)
index 0000000..688ff70
--- /dev/null
@@ -0,0 +1,84 @@
+From e1c399c0a0f5bc0f8cf762a8a9a4910d22e0304b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Jul 2020 11:34:48 +0200
+Subject: x86, vmlinux.lds: Page-align end of ..page_aligned sections
+
+From: Joerg Roedel <jroedel@suse.de>
+
+[ Upstream commit de2b41be8fcccb2f5b6c480d35df590476344201 ]
+
+On x86-32 the idt_table with 256 entries needs only 2048 bytes. It is
+page-aligned, but the end of the .bss..page_aligned section is not
+guaranteed to be page-aligned.
+
+As a result, objects from other .bss sections may end up on the same 4k
+page as the idt_table, and will accidentially get mapped read-only during
+boot, causing unexpected page-faults when the kernel writes to them.
+
+This could be worked around by making the objects in the page aligned
+sections page sized, but that's wrong.
+
+Explicit sections which store only page aligned objects have an implicit
+guarantee that the object is alone in the page in which it is placed. That
+works for all objects except the last one. That's inconsistent.
+
+Enforcing page sized objects for these sections would wreckage memory
+sanitizers, because the object becomes artificially larger than it should
+be and out of bound access becomes legit.
+
+Align the end of the .bss..page_aligned and .data..page_aligned section on
+page-size so all objects places in these sections are guaranteed to have
+their own page.
+
+[ tglx: Amended changelog ]
+
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Reviewed-by: Kees Cook <keescook@chromium.org>
+Cc: stable@vger.kernel.org
+Link: https://lkml.kernel.org/r/20200721093448.10417-1-joro@8bytes.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kernel/vmlinux.lds.S     | 1 +
+ include/asm-generic/vmlinux.lds.h | 5 ++++-
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
+index 9b185142219b9..5cdd7dc7b9941 100644
+--- a/arch/x86/kernel/vmlinux.lds.S
++++ b/arch/x86/kernel/vmlinux.lds.S
+@@ -330,6 +330,7 @@ SECTIONS
+       .bss : AT(ADDR(.bss) - LOAD_OFFSET) {
+               __bss_start = .;
+               *(.bss..page_aligned)
++              . = ALIGN(PAGE_SIZE);
+               *(BSS_MAIN)
+               . = ALIGN(PAGE_SIZE);
+               __bss_stop = .;
+diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
+index a461b6604fd9d..49e373792fc15 100644
+--- a/include/asm-generic/vmlinux.lds.h
++++ b/include/asm-generic/vmlinux.lds.h
+@@ -233,7 +233,8 @@
+ #define PAGE_ALIGNED_DATA(page_align)                                 \
+       . = ALIGN(page_align);                                          \
+-      *(.data..page_aligned)
++      *(.data..page_aligned)                                          \
++      . = ALIGN(page_align);
+ #define READ_MOSTLY_DATA(align)                                               \
+       . = ALIGN(align);                                               \
+@@ -572,7 +573,9 @@
+       . = ALIGN(bss_align);                                           \
+       .bss : AT(ADDR(.bss) - LOAD_OFFSET) {                           \
+               BSS_FIRST_SECTIONS                                      \
++              . = ALIGN(PAGE_SIZE);                                   \
+               *(.bss..page_aligned)                                   \
++              . = ALIGN(PAGE_SIZE);                                   \
+               *(.dynbss)                                              \
+               *(.bss)                                                 \
+               *(COMMON)                                               \
+-- 
+2.25.1
+