Call dwc2_debugfs_exit() and dwc2_hcd_remove() (if the HCD was enabled
earlier) when usb_add_gadget_udc() has failed. This ensures that the
debugfs entries created by dwc2_debugfs_init() as well as the HCD are
cleaned up in the error path.
Fixes: 207324a321a866 ("usb: dwc2: Postponed gadget registration to the udc class driver")
Signed-off-by: Martin Blumenstingl <martin.blumenstingl(a)googlemail.com>
---
Changes since v2 at [1]:
- add #if around the new label and it's code to prevent the following
warning found by the Kernel test robot:
unused label 'error_debugfs' [-Wunused-label]
Changes since v1 at [0]
- also cleanup the HCD as suggested by Minas (thank you!)
- updated the subject accordingly
[0] https://patchwork.kernel.org/patch/11631381/
[1] https://patchwork.kernel.org/patch/11642957/
drivers/usb/dwc2/platform.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
index cb8ddbd53718..b74099764b2d 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -583,12 +583,19 @@ static int dwc2_driver_probe(struct platform_device *dev)
retval = usb_add_gadget_udc(hsotg->dev, &hsotg->gadget);
if (retval) {
dwc2_hsotg_remove(hsotg);
- goto error_init;
+ goto error_debugfs;
}
}
#endif /* CONFIG_USB_DWC2_PERIPHERAL || CONFIG_USB_DWC2_DUAL_ROLE */
return 0;
+#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \
+ IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
+error_debugfs:
+ dwc2_debugfs_exit(hsotg);
+ if (hsotg->hcd_enabled)
+ dwc2_hcd_remove(hsotg);
+#endif
error_init:
if (hsotg->params.activate_stm_id_vb_detection)
regulator_disable(hsotg->usb33d);
--
2.27.0
Hi,
The v4.4 stable kernel (currently it's v4.4.231) lacks this bugfix:
327868212381 ("make skb_copy_datagram_msg() et.al. preserve ->msg_iter on error")
, as a result, the v4.4 kernel can deliver corrupt data to the application
when a corrupt UDP packet is closely followed by a valid UDP packet:
when the same invocation of the recvmsg() syscall delivers the corrupt
packet's UDP payload to the application's receive buffer, it provides the
UDP payload length and the "from IP/Port" of the valid packet to the
application -- this mismatch makes the issue worse.
Details:
For a UDP packet longer than 76 bytes (see the v5.8-rc6 kernel's
include/linux/skbuff.h:3951), Linux delays the UDP checksum verification
until the application invokes the syscall recvmsg().
In the recvmsg() syscall handler, while Linux is copying the UDP payload
to the application's memory, it calculates the UDP checksum. If the
calculated checksum doesn't match the received checksum, Linux drops the
corrupt UDP packet, and then starts to process the next packet (if any),
and if the next packet is valid (i.e. the checksum is correct), Linux will
copy the valid UDP packet's payload to the application's receiver buffer.
The bug is: before Linux starts to copy the valid UDP packet, the data
structure used to track how many more bytes should be copied to the
application memory is not reset to what it was when the application just
entered the kernel by the syscall! Consequently, only a small portion or
none of the valid packet's payload is copied to the application's receive
buffer, and later when the application exits from the kernel, actually
most of the application's receive buffer contains the payload of the
corrupt packet while recvmsg() returns the length of the UDP payload of
the valid packet.
For the mainline kernel, the bug was fixed by Al Viro in the commit
327868212381, but unluckily the bugfix is only backported to the
upstream v4.9+ kernels. I hope the bugfix can be backported to the
v4.4 stable kernel, since it's a "longterm" kernel and is still used by
some Linux distros.
It turns out backporting 327868212381 to v4.4 means that some
Supporting patches must be backported first, so the overall changes
are pretty big...
I made the below one-line workaround patch to force the recvmsg() syscall
handler to return to the userspace when Linux detects a corrupt UDP packet,
so the application will invoke the syscall again to receive the following valid
UDP packet (note: the patch may not work well with blocking sockets, for
which typically the application doesn't expect an error of -EAGAIN. I
guess it would be safer to return -EINTR instead?):
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1367,6 +1367,7 @@ csum_copy_err:
/* starting over for a new packet, but check if we need to yield */
cond_resched();
msg->msg_flags &= ~MSG_TRUNC;
+ return -EAGAIN;
goto try_again;
}
Eric Dumazet made an alternative that performs the csum validation earlier:
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1589,8 +1589,7 @@ int udp_queue_rcv_skb(struct sock *sk, struct
sk_buff *skb)
}
}
- if (rcu_access_pointer(sk->sk_filter) &&
- udp_lib_checksum_complete(skb))
+ if (udp_lib_checksum_complete(skb))
goto csum_error;
if (sk_rcvqueues_full(sk, sk->sk_rcvbuf)) {
I personally like Eric's fix and IMHO we'd better have it in v4.4 rather than
trying to backport 327868212381.
Looking forward to your comments!
Thanks,
Dexuan Cui
The function mipi_dbi_spi1_transfer() will transfer its payload as 9-bit
data, the 9th (MSB) bit being the data/command bit. In order to do that,
it unpacks the 8-bit values into 16-bit values, then sets the 9th bit if
the byte corresponds to data, clears it otherwise. The 7 MSB are
padding. The array of now 16-bit values is then passed to the SPI core
for transfer.
This function was broken since its introduction, as the length of the
SPI transfer was set to the payload size before its conversion, but the
payload doubled in size due to the 8-bit -> 16-bit conversion.
Fixes: 02dd95fe3169 ("drm/tinydrm: Add MIPI DBI support")
Cc: <stable(a)vger.kernel.org> # 4.10
Signed-off-by: Paul Cercueil <paul(a)crapouillou.net>
---
drivers/gpu/drm/drm_mipi_dbi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c
index bb27c82757f1..bf7888ad9ad4 100644
--- a/drivers/gpu/drm/drm_mipi_dbi.c
+++ b/drivers/gpu/drm/drm_mipi_dbi.c
@@ -923,7 +923,7 @@ static int mipi_dbi_spi1_transfer(struct mipi_dbi *dbi, int dc,
}
}
- tr.len = chunk;
+ tr.len = chunk * 2;
len -= chunk;
ret = spi_sync(spi, &m);
--
2.27.0
The atomic modesetting code tried to distinguish format changes from
full modesetting operations. In practice, this was buggy and the format
registers were often updated even for simple pageflips.
Instead do a full modeset if the primary plane changes formats. It's
just as rare as an actual mode change, so there will be no performance
penalty.
The patch also replaces a reference to drm_crtc_state.allow_modeset with
the correct call to drm_atomic_crtc_needs_modeset().
Signed-off-by: Thomas Zimmermann <tzimmermann(a)suse.de>
Fixes: 4961eb60f145 ("drm/ast: Enable atomic modesetting")
Cc: Thomas Zimmermann <tzimmermann(a)suse.de>
Cc: Gerd Hoffmann <kraxel(a)redhat.com>
Cc: Dave Airlie <airlied(a)redhat.com>
Cc: Daniel Vetter <daniel.vetter(a)ffwll.ch>
Cc: Sam Ravnborg <sam(a)ravnborg.org>
Cc: Emil Velikov <emil.l.velikov(a)gmail.com>
Cc: "Y.C. Chen" <yc_chen(a)aspeedtech.com>
Cc: <stable(a)vger.kernel.org> # v5.6+
---
drivers/gpu/drm/ast/ast_mode.c | 23 ++++++++++++++++-------
1 file changed, 16 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index 154cd877d9d1..3680a000b812 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -527,8 +527,8 @@ static const uint32_t ast_primary_plane_formats[] = {
static int ast_primary_plane_helper_atomic_check(struct drm_plane *plane,
struct drm_plane_state *state)
{
- struct drm_crtc_state *crtc_state;
- struct ast_crtc_state *ast_crtc_state;
+ struct drm_crtc_state *crtc_state, *old_crtc_state;
+ struct ast_crtc_state *ast_crtc_state, *old_ast_crtc_state;
int ret;
if (!state->crtc)
@@ -550,6 +550,15 @@ static int ast_primary_plane_helper_atomic_check(struct drm_plane *plane,
ast_crtc_state->format = state->fb->format;
+ old_crtc_state = drm_atomic_get_old_crtc_state(state->state, state->crtc);
+ if (!old_crtc_state)
+ return 0;
+ old_ast_crtc_state = to_ast_crtc_state(old_crtc_state);
+ if (!old_ast_crtc_state)
+ return 0;
+ if (ast_crtc_state->format != old_ast_crtc_state->format)
+ crtc_state->mode_changed = true;
+
return 0;
}
@@ -775,18 +784,18 @@ static void ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
ast_state = to_ast_crtc_state(crtc->state);
- format = ast_state->format;
- if (!format)
+ if (!drm_atomic_crtc_needs_modeset(crtc->state))
return;
+ format = ast_state->format;
+ if (drm_WARN_ON_ONCE(dev, !format))
+ return; /* BUG: We didn't set format in primary check(). */
+
vbios_mode_info = &ast_state->vbios_mode_info;
ast_set_color_reg(ast, format);
ast_set_vbios_color_reg(ast, format, vbios_mode_info);
- if (!crtc->state->mode_changed)
- return;
-
adjusted_mode = &crtc->state->adjusted_mode;
ast_set_vbios_mode_reg(ast, adjusted_mode, vbios_mode_info);
--
2.27.0
Call dwc2_debugfs_exit() and dwc2_hcd_remove() (if the HCD was enabled
earlier) when usb_add_gadget_udc() has failed. This ensures that the
debugfs entries created by dwc2_debugfs_init() as well as the HCD are
cleaned up in the error path.
Fixes: 207324a321a866 ("usb: dwc2: Postponed gadget registration to the udc class driver")
Signed-off-by: Martin Blumenstingl <martin.blumenstingl(a)googlemail.com>
---
Changes since v1 at [0]
- also cleanup the HCD as suggested by Minas (thank you!)
- updated the subject accordingly
[0] https://patchwork.kernel.org/patch/11631381/
drivers/usb/dwc2/platform.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
index c347d93eae64..9febae441069 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -582,12 +582,16 @@ static int dwc2_driver_probe(struct platform_device *dev)
retval = usb_add_gadget_udc(hsotg->dev, &hsotg->gadget);
if (retval) {
dwc2_hsotg_remove(hsotg);
- goto error_init;
+ goto error_debugfs;
}
}
#endif /* CONFIG_USB_DWC2_PERIPHERAL || CONFIG_USB_DWC2_DUAL_ROLE */
return 0;
+error_debugfs:
+ dwc2_debugfs_exit(hsotg);
+ if (hsotg->hcd_enabled)
+ dwc2_hcd_remove(hsotg);
error_init:
if (hsotg->params.activate_stm_id_vb_detection)
regulator_disable(hsotg->usb33d);
--
2.27.0
Hi Greg, Sasha and all the others,
Hans de Goede requested to revert "ath9k: Fix general protection fault in ath9k_hif_usb_rx_cb"
from all stable and longterm kernels because this commit broke certain devices
with Atheros 9271 and at that time it seemed that reverting the commit would be
done in the mainline kernel. The revert was done in kernel 5.7.9 etc., however
Mark O'Donovan found a fix for the original commit - which avoided the revert in
the mainline kernel - and this fix is now included in 5.8-rc7 with commit
92f53e2fda8bb9a559ad61d57bfb397ce67ed0ab ("ath9k: Fix regression with Atheros 9271").
To be consistent with the mainline kernel, please apply the original commit
again (or re-revert it, whatever is appropriate for stable kernels) and then
apply Mark's fix. I have tested this with the current 5.7.10 kernel to confirm
that it works because I was affected by the bug.
All relevant people are CC'ed if someone wants to object.
Thanks,
Viktor
The patch below does not apply to the 4.4-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable(a)vger.kernel.org>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
>From de2b41be8fcccb2f5b6c480d35df590476344201 Mon Sep 17 00:00:00 2001
From: Joerg Roedel <jroedel(a)suse.de>
Date: Tue, 21 Jul 2020 11:34:48 +0200
Subject: [PATCH] x86, vmlinux.lds: Page-align end of ..page_aligned sections
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(a)suse.de>
Signed-off-by: Thomas Gleixner <tglx(a)linutronix.de>
Reviewed-by: Kees Cook <keescook(a)chromium.org>
Cc: stable(a)vger.kernel.org
Link: https://lkml.kernel.org/r/20200721093448.10417-1-joro@8bytes.org
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 3bfc8dd8a43d..9a03e5b23135 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -358,6 +358,7 @@ SECTIONS
.bss : AT(ADDR(.bss) - LOAD_OFFSET) {
__bss_start = .;
*(.bss..page_aligned)
+ . = ALIGN(PAGE_SIZE);
*(BSS_MAIN)
BSS_DECRYPTED
. = ALIGN(PAGE_SIZE);
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index db600ef218d7..052e0f05a984 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -341,7 +341,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); \
@@ -737,7 +738,9 @@
. = ALIGN(bss_align); \
.bss : AT(ADDR(.bss) - LOAD_OFFSET) { \
BSS_FIRST_SECTIONS \
+ . = ALIGN(PAGE_SIZE); \
*(.bss..page_aligned) \
+ . = ALIGN(PAGE_SIZE); \
*(.dynbss) \
*(BSS_MAIN) \
*(COMMON) \
The patch below does not apply to the 4.9-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable(a)vger.kernel.org>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
>From de2b41be8fcccb2f5b6c480d35df590476344201 Mon Sep 17 00:00:00 2001
From: Joerg Roedel <jroedel(a)suse.de>
Date: Tue, 21 Jul 2020 11:34:48 +0200
Subject: [PATCH] x86, vmlinux.lds: Page-align end of ..page_aligned sections
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(a)suse.de>
Signed-off-by: Thomas Gleixner <tglx(a)linutronix.de>
Reviewed-by: Kees Cook <keescook(a)chromium.org>
Cc: stable(a)vger.kernel.org
Link: https://lkml.kernel.org/r/20200721093448.10417-1-joro@8bytes.org
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 3bfc8dd8a43d..9a03e5b23135 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -358,6 +358,7 @@ SECTIONS
.bss : AT(ADDR(.bss) - LOAD_OFFSET) {
__bss_start = .;
*(.bss..page_aligned)
+ . = ALIGN(PAGE_SIZE);
*(BSS_MAIN)
BSS_DECRYPTED
. = ALIGN(PAGE_SIZE);
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index db600ef218d7..052e0f05a984 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -341,7 +341,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); \
@@ -737,7 +738,9 @@
. = ALIGN(bss_align); \
.bss : AT(ADDR(.bss) - LOAD_OFFSET) { \
BSS_FIRST_SECTIONS \
+ . = ALIGN(PAGE_SIZE); \
*(.bss..page_aligned) \
+ . = ALIGN(PAGE_SIZE); \
*(.dynbss) \
*(BSS_MAIN) \
*(COMMON) \