--- /dev/null
+From dea91bcd3205ee67f1b69217c6a8ea4c0c7f68a6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 10:43:20 +0000
+Subject: media: uvcvideo: Fix sequence number when no EOF
+
+From: Ricardo Ribalda <ribalda@chromium.org>
+
+commit f078966ca1fb1b3865d8e6bbe2705cfd277fc637 upstream.
+
+If the driver could not detect the EOF, the sequence number is increased
+twice:
+ 1) When we enter uvc_video_decode_start() with the old buffer and FID has
+ flipped => We return -EAGAIN and last_fid is not flipped
+ 2) When we enter uvc_video_decode_start() with the new buffer.
+
+Fix this issue by moving the new frame detection logic earlier in
+uvc_video_decode_start().
+
+This also has some nice side affects:
+
+- The error status from the new packet will no longer get propagated
+ to the previous frame-buffer.
+- uvc_video_clock_decode() will no longer update the previous frame
+ buf->stf with info from the new packet.
+- uvc_video_clock_decode() and uvc_video_stats_decode() will no longer
+ get called twice for the same packet.
+
+Cc: stable@kernel.org
+Fixes: 650b95feee35 ("[media] uvcvideo: Generate discontinuous sequence numbers when frames are lost")
+Reported-by: Hans de Goede <hansg@kernel.org>
+Closes: https://lore.kernel.org/linux-media/CANiDSCuj4cPuB5_v2xyvAagA5FjoN8V5scXiFFOeD3aKDMqkCg@mail.gmail.com/T/#me39fb134e8c2c085567a31548c3403eb639625e4
+Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Reviewed-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
+Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
+Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
+Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/uvc/uvc_video.c | 94 ++++++++++++++++---------------
+ 1 file changed, 49 insertions(+), 45 deletions(-)
+
+diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
+index 7d462e346abd..909e158a017a 100644
+--- a/drivers/media/usb/uvc/uvc_video.c
++++ b/drivers/media/usb/uvc/uvc_video.c
+@@ -1093,7 +1093,55 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
+ header_len = data[0];
+ fid = data[1] & UVC_STREAM_FID;
+
+- /* Increase the sequence number regardless of any buffer states, so
++ /*
++ * Mark the buffer as done if we're at the beginning of a new frame.
++ * End of frame detection is better implemented by checking the EOF
++ * bit (FID bit toggling is delayed by one frame compared to the EOF
++ * bit), but some devices don't set the bit at end of frame (and the
++ * last payload can be lost anyway). We thus must check if the FID has
++ * been toggled.
++ *
++ * stream->last_fid is initialized to -1, and buf->bytesused to 0,
++ * so the first isochronous frame will never trigger an end of frame
++ * detection.
++ *
++ * Empty buffers (bytesused == 0) don't trigger end of frame detection
++ * as it doesn't make sense to return an empty buffer. This also
++ * avoids detecting end of frame conditions at FID toggling if the
++ * previous payload had the EOF bit set.
++ */
++ if (fid != stream->last_fid && buf && buf->bytesused != 0) {
++ uvc_trace(UVC_TRACE_FRAME,
++ "Frame complete (FID bit toggled)\n");
++ buf->state = UVC_BUF_STATE_READY;
++
++ return -EAGAIN;
++ }
++
++ /*
++ * Some cameras, when running two parallel streams (one MJPEG alongside
++ * another non-MJPEG stream), are known to lose the EOF packet for a frame.
++ * We can detect the end of a frame by checking for a new SOI marker, as
++ * the SOI always lies on the packet boundary between two frames for
++ * these devices.
++ */
++ if (stream->dev->quirks & UVC_QUIRK_MJPEG_NO_EOF &&
++ (stream->cur_format->fcc == V4L2_PIX_FMT_MJPEG ||
++ stream->cur_format->fcc == V4L2_PIX_FMT_JPEG) &&
++ buf && buf->bytesused != 0) {
++ const u8 *packet = data + header_len;
++
++ if (len >= header_len + 2 &&
++ packet[0] == 0xff && packet[1] == JPEG_MARKER_SOI) {
++ buf->state = UVC_BUF_STATE_READY;
++ buf->error = 1;
++ stream->last_fid ^= UVC_STREAM_FID;
++ return -EAGAIN;
++ }
++ }
++
++ /*
++ * Increase the sequence number regardless of any buffer states, so
+ * that discontinuous sequence numbers always indicate lost frames.
+ */
+ if (stream->last_fid != fid) {
+@@ -1157,50 +1205,6 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
+ meta_buf->state = UVC_BUF_STATE_ACTIVE;
+ }
+
+- /* Mark the buffer as done if we're at the beginning of a new frame.
+- * End of frame detection is better implemented by checking the EOF
+- * bit (FID bit toggling is delayed by one frame compared to the EOF
+- * bit), but some devices don't set the bit at end of frame (and the
+- * last payload can be lost anyway). We thus must check if the FID has
+- * been toggled.
+- *
+- * stream->last_fid is initialized to -1, so the first isochronous
+- * frame will never trigger an end of frame detection.
+- *
+- * Empty buffers (bytesused == 0) don't trigger end of frame detection
+- * as it doesn't make sense to return an empty buffer. This also
+- * avoids detecting end of frame conditions at FID toggling if the
+- * previous payload had the EOF bit set.
+- */
+- if (fid != stream->last_fid && buf->bytesused != 0) {
+- uvc_trace(UVC_TRACE_FRAME, "Frame complete (FID bit "
+- "toggled).\n");
+- buf->state = UVC_BUF_STATE_READY;
+- return -EAGAIN;
+- }
+-
+- /*
+- * Some cameras, when running two parallel streams (one MJPEG alongside
+- * another non-MJPEG stream), are known to lose the EOF packet for a frame.
+- * We can detect the end of a frame by checking for a new SOI marker, as
+- * the SOI always lies on the packet boundary between two frames for
+- * these devices.
+- */
+- if (stream->dev->quirks & UVC_QUIRK_MJPEG_NO_EOF &&
+- (stream->cur_format->fcc == V4L2_PIX_FMT_MJPEG ||
+- stream->cur_format->fcc == V4L2_PIX_FMT_JPEG)) {
+- const u8 *packet = data + header_len;
+-
+- if (len >= header_len + 2 &&
+- packet[0] == 0xff && packet[1] == JPEG_MARKER_SOI &&
+- buf->bytesused != 0) {
+- buf->state = UVC_BUF_STATE_READY;
+- buf->error = 1;
+- stream->last_fid ^= UVC_STREAM_FID;
+- return -EAGAIN;
+- }
+- }
+-
+ stream->last_fid = fid;
+
+ return header_len;
+--
+2.53.0
+
--- /dev/null
+From 4d8e565ccc3264f67b21b575764713cd4d330391 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 10:43:19 +0000
+Subject: media: uvcvideo: Implement dual stream quirk to fix loss of usb
+ packets
+
+From: Isaac Scott <isaac.scott@ideasonboard.com>
+
+commit c2eda35e675b6ea4a0a21a4b1167b121571a9036 upstream.
+
+Some cameras, such as the Sonix Technology Co. 292A, exhibit issues when
+running two parallel streams, causing USB packets to be dropped when an
+H.264 stream posts a keyframe while an MJPEG stream is running
+simultaneously. This occasionally causes the driver to erroneously
+output two consecutive JPEG images as a single frame.
+
+To fix this, we inspect the buffer, and trigger a new frame when we
+find an SOI.
+
+Signed-off-by: Isaac Scott <isaac.scott@ideasonboard.com>
+Reviewed-by: Ricardo Ribalda <ribalda@chromium.org>
+Link: https://lore.kernel.org/r/20241128145144.61475-2-isaac.scott@ideasonboard.com
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+[Added JPEG_MARKER_SOI definition, jpeg header does not exist yet]
+Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/uvc/uvc_video.c | 28 +++++++++++++++++++++++++++-
+ drivers/media/usb/uvc/uvcvideo.h | 4 ++++
+ 2 files changed, 31 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
+index 1a8a89aa0c5c..7d462e346abd 100644
+--- a/drivers/media/usb/uvc/uvc_video.c
++++ b/drivers/media/usb/uvc/uvc_video.c
+@@ -21,6 +21,8 @@
+
+ #include "uvcvideo.h"
+
++#define JPEG_MARKER_SOI 0xd8
++
+ /* ------------------------------------------------------------------------
+ * UVC Controls
+ */
+@@ -1075,6 +1077,7 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
+ struct uvc_buffer *meta_buf,
+ const u8 *data, int len)
+ {
++ u8 header_len;
+ u8 fid;
+
+ /* Sanity checks:
+@@ -1087,6 +1090,7 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
+ return -EINVAL;
+ }
+
++ header_len = data[0];
+ fid = data[1] & UVC_STREAM_FID;
+
+ /* Increase the sequence number regardless of any buffer states, so
+@@ -1175,9 +1179,31 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
+ return -EAGAIN;
+ }
+
++ /*
++ * Some cameras, when running two parallel streams (one MJPEG alongside
++ * another non-MJPEG stream), are known to lose the EOF packet for a frame.
++ * We can detect the end of a frame by checking for a new SOI marker, as
++ * the SOI always lies on the packet boundary between two frames for
++ * these devices.
++ */
++ if (stream->dev->quirks & UVC_QUIRK_MJPEG_NO_EOF &&
++ (stream->cur_format->fcc == V4L2_PIX_FMT_MJPEG ||
++ stream->cur_format->fcc == V4L2_PIX_FMT_JPEG)) {
++ const u8 *packet = data + header_len;
++
++ if (len >= header_len + 2 &&
++ packet[0] == 0xff && packet[1] == JPEG_MARKER_SOI &&
++ buf->bytesused != 0) {
++ buf->state = UVC_BUF_STATE_READY;
++ buf->error = 1;
++ stream->last_fid ^= UVC_STREAM_FID;
++ return -EAGAIN;
++ }
++ }
++
+ stream->last_fid = fid;
+
+- return data[0];
++ return header_len;
+ }
+
+ /*
+diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
+index a83995276170..4a1ff08453d7 100644
+--- a/drivers/media/usb/uvc/uvcvideo.h
++++ b/drivers/media/usb/uvc/uvcvideo.h
+@@ -204,6 +204,10 @@
+ #define UVC_QUIRK_FORCE_Y8 0x00000800
+ #define UVC_QUIRK_FORCE_BPP 0x00001000
+ #define UVC_QUIRK_WAKE_AUTOSUSPEND 0x00002000
++#define UVC_QUIRK_NO_RESET_RESUME 0x00004000
++#define UVC_QUIRK_DISABLE_AUTOSUSPEND 0x00008000
++#define UVC_QUIRK_INVALID_DEVICE_SOF 0x00010000
++#define UVC_QUIRK_MJPEG_NO_EOF 0x00020000
+
+ /* Format flags */
+ #define UVC_FMT_FLAG_COMPRESSED 0x00000001
+--
+2.53.0
+
--- /dev/null
+From 006dbf7b421df18e7ca652dc22b48de48c0a5dee Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jul 2026 10:08:29 +0900
+Subject: net: mpls: initialize rtm_tos in mpls_getroute()
+
+From: Yehyeong Lee <yhlee@isslab.korea.ac.kr>
+
+[ Upstream commit 295dd295e2137e10e9a5b1891d97e0f08de76f03 ]
+
+mpls_getroute() builds the RTM_NEWROUTE reply to an RTM_GETROUTE
+request by filling a struct rtmsg allocated from an skb whose data
+area is not zeroed (alloc_skb(NLMSG_GOODSIZE, ...)). It sets every
+field of the header except rtm_tos:
+
+ r = nlmsg_data(nlh);
+ r->rtm_family = AF_MPLS;
+ r->rtm_dst_len = 20;
+ r->rtm_src_len = 0;
+ r->rtm_table = RT_TABLE_MAIN;
+ r->rtm_type = RTN_UNICAST;
+ r->rtm_scope = RT_SCOPE_UNIVERSE;
+ r->rtm_protocol = rt->rt_protocol;
+ r->rtm_flags = 0;
+
+struct rtmsg has no padding, so the one uninitialised byte rtm_tos
+(offset 3) is copied straight to user space on recvmsg(), leaking a
+byte of uninitialised heap memory. This is in contrast to
+mpls_dump_route(), which fills the very same header and does set
+rtm_tos = 0.
+
+Initialize rtm_tos to 0, matching mpls_dump_route().
+
+Reproduced with KMSAN by adding an MPLS route and issuing a
+non-RTM_F_FIB_MATCH RTM_GETROUTE for its label:
+
+ BUG: KMSAN: kernel-infoleak in _copy_to_iter+0x36c/0x33f0
+ _copy_to_iter+0x36c/0x33f0
+ __skb_datagram_iter+0x196/0x12c0
+ skb_copy_datagram_iter+0x5b/0x210
+ netlink_recvmsg+0x37b/0xef0
+ ...
+ Uninit was created at:
+ __alloc_skb+0x8ca/0x10e0
+ mpls_getroute+0x1280/0x3a40
+ rtnetlink_rcv_msg+0x1138/0x15a0
+ ...
+ Byte 19 of 64 is uninitialized
+
+(byte 19 = nlmsghdr(16) + rtmsg offset 3 = rtm_tos)
+
+Fixes: 397fc9e5cefe ("mpls: route get support")
+Signed-off-by: Yehyeong Lee <yhlee@isslab.korea.ac.kr>
+Link: https://patch.msgid.link/20260723010830.289917-1-yhlee@isslab.korea.ac.kr
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mpls/af_mpls.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
+index 66f498667ed8..5c80fb93bb7a 100644
+--- a/net/mpls/af_mpls.c
++++ b/net/mpls/af_mpls.c
+@@ -2492,6 +2492,7 @@ static int mpls_getroute(struct sk_buff *in_skb, struct nlmsghdr *in_nlh,
+ r->rtm_family = AF_MPLS;
+ r->rtm_dst_len = 20;
+ r->rtm_src_len = 0;
++ r->rtm_tos = 0;
+ r->rtm_table = RT_TABLE_MAIN;
+ r->rtm_type = RTN_UNICAST;
+ r->rtm_scope = RT_SCOPE_UNIVERSE;
+--
+2.53.0
+
--- /dev/null
+net-mpls-initialize-rtm_tos-in-mpls_getroute.patch
+media-uvcvideo-implement-dual-stream-quirk-to-fix-lo.patch
+media-uvcvideo-fix-sequence-number-when-no-eof.patch
--- /dev/null
+From b60af3c20395afe4a364be38a954cb89a625a2e6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 10:48:33 +0000
+Subject: media: uvcvideo: Fix sequence number when no EOF
+
+From: Ricardo Ribalda <ribalda@chromium.org>
+
+commit f078966ca1fb1b3865d8e6bbe2705cfd277fc637 upstream.
+
+If the driver could not detect the EOF, the sequence number is increased
+twice:
+ 1) When we enter uvc_video_decode_start() with the old buffer and FID has
+ flipped => We return -EAGAIN and last_fid is not flipped
+ 2) When we enter uvc_video_decode_start() with the new buffer.
+
+Fix this issue by moving the new frame detection logic earlier in
+uvc_video_decode_start().
+
+This also has some nice side affects:
+
+- The error status from the new packet will no longer get propagated
+ to the previous frame-buffer.
+- uvc_video_clock_decode() will no longer update the previous frame
+ buf->stf with info from the new packet.
+- uvc_video_clock_decode() and uvc_video_stats_decode() will no longer
+ get called twice for the same packet.
+
+Cc: stable@kernel.org
+Fixes: 650b95feee35 ("[media] uvcvideo: Generate discontinuous sequence numbers when frames are lost")
+Reported-by: Hans de Goede <hansg@kernel.org>
+Closes: https://lore.kernel.org/linux-media/CANiDSCuj4cPuB5_v2xyvAagA5FjoN8V5scXiFFOeD3aKDMqkCg@mail.gmail.com/T/#me39fb134e8c2c085567a31548c3403eb639625e4
+Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Reviewed-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
+Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
+Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
+Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/uvc/uvc_video.c | 94 ++++++++++++++++---------------
+ 1 file changed, 49 insertions(+), 45 deletions(-)
+
+diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
+index 2a2c10daa07a..d0415ebe54d0 100644
+--- a/drivers/media/usb/uvc/uvc_video.c
++++ b/drivers/media/usb/uvc/uvc_video.c
+@@ -1095,7 +1095,55 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
+ header_len = data[0];
+ fid = data[1] & UVC_STREAM_FID;
+
+- /* Increase the sequence number regardless of any buffer states, so
++ /*
++ * Mark the buffer as done if we're at the beginning of a new frame.
++ * End of frame detection is better implemented by checking the EOF
++ * bit (FID bit toggling is delayed by one frame compared to the EOF
++ * bit), but some devices don't set the bit at end of frame (and the
++ * last payload can be lost anyway). We thus must check if the FID has
++ * been toggled.
++ *
++ * stream->last_fid is initialized to -1, and buf->bytesused to 0,
++ * so the first isochronous frame will never trigger an end of frame
++ * detection.
++ *
++ * Empty buffers (bytesused == 0) don't trigger end of frame detection
++ * as it doesn't make sense to return an empty buffer. This also
++ * avoids detecting end of frame conditions at FID toggling if the
++ * previous payload had the EOF bit set.
++ */
++ if (fid != stream->last_fid && buf && buf->bytesused != 0) {
++ uvc_dbg(stream->dev, FRAME,
++ "Frame complete (FID bit toggled)\n");
++ buf->state = UVC_BUF_STATE_READY;
++
++ return -EAGAIN;
++ }
++
++ /*
++ * Some cameras, when running two parallel streams (one MJPEG alongside
++ * another non-MJPEG stream), are known to lose the EOF packet for a frame.
++ * We can detect the end of a frame by checking for a new SOI marker, as
++ * the SOI always lies on the packet boundary between two frames for
++ * these devices.
++ */
++ if (stream->dev->quirks & UVC_QUIRK_MJPEG_NO_EOF &&
++ (stream->cur_format->fcc == V4L2_PIX_FMT_MJPEG ||
++ stream->cur_format->fcc == V4L2_PIX_FMT_JPEG) &&
++ buf && buf->bytesused != 0) {
++ const u8 *packet = data + header_len;
++
++ if (len >= header_len + 2 &&
++ packet[0] == 0xff && packet[1] == JPEG_MARKER_SOI) {
++ buf->state = UVC_BUF_STATE_READY;
++ buf->error = 1;
++ stream->last_fid ^= UVC_STREAM_FID;
++ return -EAGAIN;
++ }
++ }
++
++ /*
++ * Increase the sequence number regardless of any buffer states, so
+ * that discontinuous sequence numbers always indicate lost frames.
+ */
+ if (stream->last_fid != fid) {
+@@ -1159,50 +1207,6 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
+ meta_buf->state = UVC_BUF_STATE_ACTIVE;
+ }
+
+- /* Mark the buffer as done if we're at the beginning of a new frame.
+- * End of frame detection is better implemented by checking the EOF
+- * bit (FID bit toggling is delayed by one frame compared to the EOF
+- * bit), but some devices don't set the bit at end of frame (and the
+- * last payload can be lost anyway). We thus must check if the FID has
+- * been toggled.
+- *
+- * stream->last_fid is initialized to -1, so the first isochronous
+- * frame will never trigger an end of frame detection.
+- *
+- * Empty buffers (bytesused == 0) don't trigger end of frame detection
+- * as it doesn't make sense to return an empty buffer. This also
+- * avoids detecting end of frame conditions at FID toggling if the
+- * previous payload had the EOF bit set.
+- */
+- if (fid != stream->last_fid && buf->bytesused != 0) {
+- uvc_dbg(stream->dev, FRAME,
+- "Frame complete (FID bit toggled)\n");
+- buf->state = UVC_BUF_STATE_READY;
+- return -EAGAIN;
+- }
+-
+- /*
+- * Some cameras, when running two parallel streams (one MJPEG alongside
+- * another non-MJPEG stream), are known to lose the EOF packet for a frame.
+- * We can detect the end of a frame by checking for a new SOI marker, as
+- * the SOI always lies on the packet boundary between two frames for
+- * these devices.
+- */
+- if (stream->dev->quirks & UVC_QUIRK_MJPEG_NO_EOF &&
+- (stream->cur_format->fcc == V4L2_PIX_FMT_MJPEG ||
+- stream->cur_format->fcc == V4L2_PIX_FMT_JPEG)) {
+- const u8 *packet = data + header_len;
+-
+- if (len >= header_len + 2 &&
+- packet[0] == 0xff && packet[1] == JPEG_MARKER_SOI &&
+- buf->bytesused != 0) {
+- buf->state = UVC_BUF_STATE_READY;
+- buf->error = 1;
+- stream->last_fid ^= UVC_STREAM_FID;
+- return -EAGAIN;
+- }
+- }
+-
+ stream->last_fid = fid;
+
+ return header_len;
+--
+2.53.0
+
--- /dev/null
+From 0c5a192d9c2389203f6f1e951c11829d9c2129f4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 10:48:32 +0000
+Subject: media: uvcvideo: Implement dual stream quirk to fix loss of usb
+ packets
+
+From: Isaac Scott <isaac.scott@ideasonboard.com>
+
+commit c2eda35e675b6ea4a0a21a4b1167b121571a9036 upstream.
+
+Some cameras, such as the Sonix Technology Co. 292A, exhibit issues when
+running two parallel streams, causing USB packets to be dropped when an
+H.264 stream posts a keyframe while an MJPEG stream is running
+simultaneously. This occasionally causes the driver to erroneously
+output two consecutive JPEG images as a single frame.
+
+To fix this, we inspect the buffer, and trigger a new frame when we
+find an SOI.
+
+Signed-off-by: Isaac Scott <isaac.scott@ideasonboard.com>
+Reviewed-by: Ricardo Ribalda <ribalda@chromium.org>
+Link: https://lore.kernel.org/r/20241128145144.61475-2-isaac.scott@ideasonboard.com
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+[Added JPEG_MARKER_SOI definition, jpeg header does not exist yet]
+Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/uvc/uvc_video.c | 28 +++++++++++++++++++++++++++-
+ drivers/media/usb/uvc/uvcvideo.h | 4 ++++
+ 2 files changed, 31 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
+index 3184308e6896..2a2c10daa07a 100644
+--- a/drivers/media/usb/uvc/uvc_video.c
++++ b/drivers/media/usb/uvc/uvc_video.c
+@@ -24,6 +24,8 @@
+
+ #include "uvcvideo.h"
+
++#define JPEG_MARKER_SOI 0xd8
++
+ /* ------------------------------------------------------------------------
+ * UVC Controls
+ */
+@@ -1077,6 +1079,7 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
+ struct uvc_buffer *meta_buf,
+ const u8 *data, int len)
+ {
++ u8 header_len;
+ u8 fid;
+
+ /* Sanity checks:
+@@ -1089,6 +1092,7 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
+ return -EINVAL;
+ }
+
++ header_len = data[0];
+ fid = data[1] & UVC_STREAM_FID;
+
+ /* Increase the sequence number regardless of any buffer states, so
+@@ -1177,9 +1181,31 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
+ return -EAGAIN;
+ }
+
++ /*
++ * Some cameras, when running two parallel streams (one MJPEG alongside
++ * another non-MJPEG stream), are known to lose the EOF packet for a frame.
++ * We can detect the end of a frame by checking for a new SOI marker, as
++ * the SOI always lies on the packet boundary between two frames for
++ * these devices.
++ */
++ if (stream->dev->quirks & UVC_QUIRK_MJPEG_NO_EOF &&
++ (stream->cur_format->fcc == V4L2_PIX_FMT_MJPEG ||
++ stream->cur_format->fcc == V4L2_PIX_FMT_JPEG)) {
++ const u8 *packet = data + header_len;
++
++ if (len >= header_len + 2 &&
++ packet[0] == 0xff && packet[1] == JPEG_MARKER_SOI &&
++ buf->bytesused != 0) {
++ buf->state = UVC_BUF_STATE_READY;
++ buf->error = 1;
++ stream->last_fid ^= UVC_STREAM_FID;
++ return -EAGAIN;
++ }
++ }
++
+ stream->last_fid = fid;
+
+- return data[0];
++ return header_len;
+ }
+
+ static inline enum dma_data_direction uvc_stream_dir(
+diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
+index be4b746d902c..2dd8d04589ab 100644
+--- a/drivers/media/usb/uvc/uvcvideo.h
++++ b/drivers/media/usb/uvc/uvcvideo.h
+@@ -212,6 +212,10 @@
+ #define UVC_QUIRK_FORCE_Y8 0x00000800
+ #define UVC_QUIRK_FORCE_BPP 0x00001000
+ #define UVC_QUIRK_WAKE_AUTOSUSPEND 0x00002000
++#define UVC_QUIRK_NO_RESET_RESUME 0x00004000
++#define UVC_QUIRK_DISABLE_AUTOSUSPEND 0x00008000
++#define UVC_QUIRK_INVALID_DEVICE_SOF 0x00010000
++#define UVC_QUIRK_MJPEG_NO_EOF 0x00020000
+
+ /* Format flags */
+ #define UVC_FMT_FLAG_COMPRESSED 0x00000001
+--
+2.53.0
+
--- /dev/null
+From 4044c7986bb3746f4f1b05bbda25088e0fdb8343 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jul 2026 10:08:29 +0900
+Subject: net: mpls: initialize rtm_tos in mpls_getroute()
+
+From: Yehyeong Lee <yhlee@isslab.korea.ac.kr>
+
+[ Upstream commit 295dd295e2137e10e9a5b1891d97e0f08de76f03 ]
+
+mpls_getroute() builds the RTM_NEWROUTE reply to an RTM_GETROUTE
+request by filling a struct rtmsg allocated from an skb whose data
+area is not zeroed (alloc_skb(NLMSG_GOODSIZE, ...)). It sets every
+field of the header except rtm_tos:
+
+ r = nlmsg_data(nlh);
+ r->rtm_family = AF_MPLS;
+ r->rtm_dst_len = 20;
+ r->rtm_src_len = 0;
+ r->rtm_table = RT_TABLE_MAIN;
+ r->rtm_type = RTN_UNICAST;
+ r->rtm_scope = RT_SCOPE_UNIVERSE;
+ r->rtm_protocol = rt->rt_protocol;
+ r->rtm_flags = 0;
+
+struct rtmsg has no padding, so the one uninitialised byte rtm_tos
+(offset 3) is copied straight to user space on recvmsg(), leaking a
+byte of uninitialised heap memory. This is in contrast to
+mpls_dump_route(), which fills the very same header and does set
+rtm_tos = 0.
+
+Initialize rtm_tos to 0, matching mpls_dump_route().
+
+Reproduced with KMSAN by adding an MPLS route and issuing a
+non-RTM_F_FIB_MATCH RTM_GETROUTE for its label:
+
+ BUG: KMSAN: kernel-infoleak in _copy_to_iter+0x36c/0x33f0
+ _copy_to_iter+0x36c/0x33f0
+ __skb_datagram_iter+0x196/0x12c0
+ skb_copy_datagram_iter+0x5b/0x210
+ netlink_recvmsg+0x37b/0xef0
+ ...
+ Uninit was created at:
+ __alloc_skb+0x8ca/0x10e0
+ mpls_getroute+0x1280/0x3a40
+ rtnetlink_rcv_msg+0x1138/0x15a0
+ ...
+ Byte 19 of 64 is uninitialized
+
+(byte 19 = nlmsghdr(16) + rtmsg offset 3 = rtm_tos)
+
+Fixes: 397fc9e5cefe ("mpls: route get support")
+Signed-off-by: Yehyeong Lee <yhlee@isslab.korea.ac.kr>
+Link: https://patch.msgid.link/20260723010830.289917-1-yhlee@isslab.korea.ac.kr
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mpls/af_mpls.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
+index bd84c9ddb006..d77e028aed23 100644
+--- a/net/mpls/af_mpls.c
++++ b/net/mpls/af_mpls.c
+@@ -2495,6 +2495,7 @@ static int mpls_getroute(struct sk_buff *in_skb, struct nlmsghdr *in_nlh,
+ r->rtm_family = AF_MPLS;
+ r->rtm_dst_len = 20;
+ r->rtm_src_len = 0;
++ r->rtm_tos = 0;
+ r->rtm_table = RT_TABLE_MAIN;
+ r->rtm_type = RTN_UNICAST;
+ r->rtm_scope = RT_SCOPE_UNIVERSE;
+--
+2.53.0
+
--- /dev/null
+net-mpls-initialize-rtm_tos-in-mpls_getroute.patch
+media-uvcvideo-implement-dual-stream-quirk-to-fix-lo.patch
+media-uvcvideo-fix-sequence-number-when-no-eof.patch
--- /dev/null
+From 60635162af7211f55bcd12ded6e65ee47692448a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 10:52:23 +0000
+Subject: media: uvcvideo: Fix sequence number when no EOF
+
+From: Ricardo Ribalda <ribalda@chromium.org>
+
+commit f078966ca1fb1b3865d8e6bbe2705cfd277fc637 upstream.
+
+If the driver could not detect the EOF, the sequence number is increased
+twice:
+ 1) When we enter uvc_video_decode_start() with the old buffer and FID has
+ flipped => We return -EAGAIN and last_fid is not flipped
+ 2) When we enter uvc_video_decode_start() with the new buffer.
+
+Fix this issue by moving the new frame detection logic earlier in
+uvc_video_decode_start().
+
+This also has some nice side affects:
+
+- The error status from the new packet will no longer get propagated
+ to the previous frame-buffer.
+- uvc_video_clock_decode() will no longer update the previous frame
+ buf->stf with info from the new packet.
+- uvc_video_clock_decode() and uvc_video_stats_decode() will no longer
+ get called twice for the same packet.
+
+Cc: stable@kernel.org
+Fixes: 650b95feee35 ("[media] uvcvideo: Generate discontinuous sequence numbers when frames are lost")
+Reported-by: Hans de Goede <hansg@kernel.org>
+Closes: https://lore.kernel.org/linux-media/CANiDSCuj4cPuB5_v2xyvAagA5FjoN8V5scXiFFOeD3aKDMqkCg@mail.gmail.com/T/#me39fb134e8c2c085567a31548c3403eb639625e4
+Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Reviewed-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
+Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
+Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
+Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/uvc/uvc_video.c | 92 ++++++++++++++++---------------
+ 1 file changed, 47 insertions(+), 45 deletions(-)
+
+diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
+index 408be24fceea..2cc00f4be793 100644
+--- a/drivers/media/usb/uvc/uvc_video.c
++++ b/drivers/media/usb/uvc/uvc_video.c
+@@ -1108,6 +1108,53 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
+ header_len = data[0];
+ fid = data[1] & UVC_STREAM_FID;
+
++ /*
++ * Mark the buffer as done if we're at the beginning of a new frame.
++ * End of frame detection is better implemented by checking the EOF
++ * bit (FID bit toggling is delayed by one frame compared to the EOF
++ * bit), but some devices don't set the bit at end of frame (and the
++ * last payload can be lost anyway). We thus must check if the FID has
++ * been toggled.
++ *
++ * stream->last_fid is initialized to -1, and buf->bytesused to 0,
++ * so the first isochronous frame will never trigger an end of frame
++ * detection.
++ *
++ * Empty buffers (bytesused == 0) don't trigger end of frame detection
++ * as it doesn't make sense to return an empty buffer. This also
++ * avoids detecting end of frame conditions at FID toggling if the
++ * previous payload had the EOF bit set.
++ */
++ if (fid != stream->last_fid && buf && buf->bytesused != 0) {
++ uvc_dbg(stream->dev, FRAME,
++ "Frame complete (FID bit toggled)\n");
++ buf->state = UVC_BUF_STATE_READY;
++
++ return -EAGAIN;
++ }
++
++ /*
++ * Some cameras, when running two parallel streams (one MJPEG alongside
++ * another non-MJPEG stream), are known to lose the EOF packet for a frame.
++ * We can detect the end of a frame by checking for a new SOI marker, as
++ * the SOI always lies on the packet boundary between two frames for
++ * these devices.
++ */
++ if (stream->dev->quirks & UVC_QUIRK_MJPEG_NO_EOF &&
++ (stream->cur_format->fcc == V4L2_PIX_FMT_MJPEG ||
++ stream->cur_format->fcc == V4L2_PIX_FMT_JPEG) &&
++ buf && buf->bytesused != 0) {
++ const u8 *packet = data + header_len;
++
++ if (len >= header_len + 2 &&
++ packet[0] == 0xff && packet[1] == JPEG_MARKER_SOI) {
++ buf->state = UVC_BUF_STATE_READY;
++ buf->error = 1;
++ stream->last_fid ^= UVC_STREAM_FID;
++ return -EAGAIN;
++ }
++ }
++
+ /*
+ * Increase the sequence number regardless of any buffer states, so
+ * that discontinuous sequence numbers always indicate lost frames.
+@@ -1175,51 +1222,6 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
+ meta_buf->state = UVC_BUF_STATE_ACTIVE;
+ }
+
+- /*
+- * Mark the buffer as done if we're at the beginning of a new frame.
+- * End of frame detection is better implemented by checking the EOF
+- * bit (FID bit toggling is delayed by one frame compared to the EOF
+- * bit), but some devices don't set the bit at end of frame (and the
+- * last payload can be lost anyway). We thus must check if the FID has
+- * been toggled.
+- *
+- * stream->last_fid is initialized to -1, so the first isochronous
+- * frame will never trigger an end of frame detection.
+- *
+- * Empty buffers (bytesused == 0) don't trigger end of frame detection
+- * as it doesn't make sense to return an empty buffer. This also
+- * avoids detecting end of frame conditions at FID toggling if the
+- * previous payload had the EOF bit set.
+- */
+- if (fid != stream->last_fid && buf->bytesused != 0) {
+- uvc_dbg(stream->dev, FRAME,
+- "Frame complete (FID bit toggled)\n");
+- buf->state = UVC_BUF_STATE_READY;
+- return -EAGAIN;
+- }
+-
+- /*
+- * Some cameras, when running two parallel streams (one MJPEG alongside
+- * another non-MJPEG stream), are known to lose the EOF packet for a frame.
+- * We can detect the end of a frame by checking for a new SOI marker, as
+- * the SOI always lies on the packet boundary between two frames for
+- * these devices.
+- */
+- if (stream->dev->quirks & UVC_QUIRK_MJPEG_NO_EOF &&
+- (stream->cur_format->fcc == V4L2_PIX_FMT_MJPEG ||
+- stream->cur_format->fcc == V4L2_PIX_FMT_JPEG)) {
+- const u8 *packet = data + header_len;
+-
+- if (len >= header_len + 2 &&
+- packet[0] == 0xff && packet[1] == JPEG_MARKER_SOI &&
+- buf->bytesused != 0) {
+- buf->state = UVC_BUF_STATE_READY;
+- buf->error = 1;
+- stream->last_fid ^= UVC_STREAM_FID;
+- return -EAGAIN;
+- }
+- }
+-
+ stream->last_fid = fid;
+
+ return header_len;
+--
+2.53.0
+
--- /dev/null
+From fad444426a785df6855987c7fbbc0a893ad1bdd1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 10:52:22 +0000
+Subject: media: uvcvideo: Implement dual stream quirk to fix loss of usb
+ packets
+
+From: Isaac Scott <isaac.scott@ideasonboard.com>
+
+commit c2eda35e675b6ea4a0a21a4b1167b121571a9036 upstream.
+
+Some cameras, such as the Sonix Technology Co. 292A, exhibit issues when
+running two parallel streams, causing USB packets to be dropped when an
+H.264 stream posts a keyframe while an MJPEG stream is running
+simultaneously. This occasionally causes the driver to erroneously
+output two consecutive JPEG images as a single frame.
+
+To fix this, we inspect the buffer, and trigger a new frame when we
+find an SOI.
+
+Signed-off-by: Isaac Scott <isaac.scott@ideasonboard.com>
+Reviewed-by: Ricardo Ribalda <ribalda@chromium.org>
+Link: https://lore.kernel.org/r/20241128145144.61475-2-isaac.scott@ideasonboard.com
+Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+[Added JPEG_MARKER_SOI definition, jpeg header does not exist yet]
+Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/uvc/uvc_video.c | 28 +++++++++++++++++++++++++++-
+ drivers/media/usb/uvc/uvcvideo.h | 4 ++++
+ 2 files changed, 31 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
+index e33b9bedddda..408be24fceea 100644
+--- a/drivers/media/usb/uvc/uvc_video.c
++++ b/drivers/media/usb/uvc/uvc_video.c
+@@ -24,6 +24,8 @@
+
+ #include "uvcvideo.h"
+
++#define JPEG_MARKER_SOI 0xd8
++
+ /* ------------------------------------------------------------------------
+ * UVC Controls
+ */
+@@ -1089,6 +1091,7 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
+ struct uvc_buffer *meta_buf,
+ const u8 *data, int len)
+ {
++ u8 header_len;
+ u8 fid;
+
+ /*
+@@ -1102,6 +1105,7 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
+ return -EINVAL;
+ }
+
++ header_len = data[0];
+ fid = data[1] & UVC_STREAM_FID;
+
+ /*
+@@ -1194,9 +1198,31 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
+ return -EAGAIN;
+ }
+
++ /*
++ * Some cameras, when running two parallel streams (one MJPEG alongside
++ * another non-MJPEG stream), are known to lose the EOF packet for a frame.
++ * We can detect the end of a frame by checking for a new SOI marker, as
++ * the SOI always lies on the packet boundary between two frames for
++ * these devices.
++ */
++ if (stream->dev->quirks & UVC_QUIRK_MJPEG_NO_EOF &&
++ (stream->cur_format->fcc == V4L2_PIX_FMT_MJPEG ||
++ stream->cur_format->fcc == V4L2_PIX_FMT_JPEG)) {
++ const u8 *packet = data + header_len;
++
++ if (len >= header_len + 2 &&
++ packet[0] == 0xff && packet[1] == JPEG_MARKER_SOI &&
++ buf->bytesused != 0) {
++ buf->state = UVC_BUF_STATE_READY;
++ buf->error = 1;
++ stream->last_fid ^= UVC_STREAM_FID;
++ return -EAGAIN;
++ }
++ }
++
+ stream->last_fid = fid;
+
+- return data[0];
++ return header_len;
+ }
+
+ static inline enum dma_data_direction uvc_stream_dir(
+diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
+index a7182305390b..8404814fa899 100644
+--- a/drivers/media/usb/uvc/uvcvideo.h
++++ b/drivers/media/usb/uvc/uvcvideo.h
+@@ -77,6 +77,10 @@
+ #define UVC_QUIRK_FORCE_Y8 0x00000800
+ #define UVC_QUIRK_FORCE_BPP 0x00001000
+ #define UVC_QUIRK_WAKE_AUTOSUSPEND 0x00002000
++#define UVC_QUIRK_NO_RESET_RESUME 0x00004000
++#define UVC_QUIRK_DISABLE_AUTOSUSPEND 0x00008000
++#define UVC_QUIRK_INVALID_DEVICE_SOF 0x00010000
++#define UVC_QUIRK_MJPEG_NO_EOF 0x00020000
+
+ /* Format flags */
+ #define UVC_FMT_FLAG_COMPRESSED 0x00000001
+--
+2.53.0
+
--- /dev/null
+From e2784b54299ddcbc5b097aa122700eee428dfe1a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jul 2026 10:08:29 +0900
+Subject: net: mpls: initialize rtm_tos in mpls_getroute()
+
+From: Yehyeong Lee <yhlee@isslab.korea.ac.kr>
+
+[ Upstream commit 295dd295e2137e10e9a5b1891d97e0f08de76f03 ]
+
+mpls_getroute() builds the RTM_NEWROUTE reply to an RTM_GETROUTE
+request by filling a struct rtmsg allocated from an skb whose data
+area is not zeroed (alloc_skb(NLMSG_GOODSIZE, ...)). It sets every
+field of the header except rtm_tos:
+
+ r = nlmsg_data(nlh);
+ r->rtm_family = AF_MPLS;
+ r->rtm_dst_len = 20;
+ r->rtm_src_len = 0;
+ r->rtm_table = RT_TABLE_MAIN;
+ r->rtm_type = RTN_UNICAST;
+ r->rtm_scope = RT_SCOPE_UNIVERSE;
+ r->rtm_protocol = rt->rt_protocol;
+ r->rtm_flags = 0;
+
+struct rtmsg has no padding, so the one uninitialised byte rtm_tos
+(offset 3) is copied straight to user space on recvmsg(), leaking a
+byte of uninitialised heap memory. This is in contrast to
+mpls_dump_route(), which fills the very same header and does set
+rtm_tos = 0.
+
+Initialize rtm_tos to 0, matching mpls_dump_route().
+
+Reproduced with KMSAN by adding an MPLS route and issuing a
+non-RTM_F_FIB_MATCH RTM_GETROUTE for its label:
+
+ BUG: KMSAN: kernel-infoleak in _copy_to_iter+0x36c/0x33f0
+ _copy_to_iter+0x36c/0x33f0
+ __skb_datagram_iter+0x196/0x12c0
+ skb_copy_datagram_iter+0x5b/0x210
+ netlink_recvmsg+0x37b/0xef0
+ ...
+ Uninit was created at:
+ __alloc_skb+0x8ca/0x10e0
+ mpls_getroute+0x1280/0x3a40
+ rtnetlink_rcv_msg+0x1138/0x15a0
+ ...
+ Byte 19 of 64 is uninitialized
+
+(byte 19 = nlmsghdr(16) + rtmsg offset 3 = rtm_tos)
+
+Fixes: 397fc9e5cefe ("mpls: route get support")
+Signed-off-by: Yehyeong Lee <yhlee@isslab.korea.ac.kr>
+Link: https://patch.msgid.link/20260723010830.289917-1-yhlee@isslab.korea.ac.kr
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mpls/af_mpls.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
+index 6369ff87f4b9..11131f6a5a94 100644
+--- a/net/mpls/af_mpls.c
++++ b/net/mpls/af_mpls.c
+@@ -2483,6 +2483,7 @@ static int mpls_getroute(struct sk_buff *in_skb, struct nlmsghdr *in_nlh,
+ r->rtm_family = AF_MPLS;
+ r->rtm_dst_len = 20;
+ r->rtm_src_len = 0;
++ r->rtm_tos = 0;
+ r->rtm_table = RT_TABLE_MAIN;
+ r->rtm_type = RTN_UNICAST;
+ r->rtm_scope = RT_SCOPE_UNIVERSE;
+--
+2.53.0
+
--- /dev/null
+From 212df0069a67885c08e01baedcf628a63ec24830 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 May 2026 16:46:38 +0200
+Subject: netfilter: br_netfilter: Reallocate headroom if necessary in
+ neigh_hh_bridge()
+
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+
+[ Upstream commit b2870fc21601db9133bc70c48c603b487614fa3b ]
+
+neigh_hh_bridge() assumes the skb always has sufficient headroom to copy
+the aligned L2 header. This assumption can trigger the crash reported
+below using the following netfilter setup:
+
+$modprobe br_netfilter
+$sysctl -w net.bridge.bridge-nf-call-iptables=1
+
+$root@OpenWrt:~# nft list ruleset
+table ip nat {
+ chain prerouting {
+ type nat hook prerouting priority dstnat; policy accept;
+ ip daddr 192.168.83.123 dnat to 192.168.83.120
+ }
+}
+
+- iperf3 client (192.168.83.119) --> bridge (192.168.83.118) --> iperf3 server (192.168.83.120)
+
+the iperf3 client is sending packet for 192.168.83.123 to the bridge device.
+
+[ 1579.036575] Unable to handle kernel write to read-only memory at virtual address ffffff8004d76ffe
+[ 1579.045482] Mem abort info:
+[ 1579.048273] ESR = 0x000000009600004f
+[ 1579.052024] EC = 0x25: DABT (current EL), IL = 32 bits
+[ 1579.057363] SET = 0, FnV = 0
+[ 1579.060417] EA = 0, S1PTW = 0
+[ 1579.063550] FSC = 0x0f: level 3 permission fault
+[ 1579.068345] Data abort info:
+[ 1579.071224] ISV = 0, ISS = 0x0000004f, ISS2 = 0x00000000
+[ 1579.076720] CM = 0, WnR = 1, TnD = 0, TagAccess = 0
+[ 1579.081770] GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
+[ 1579.087092] swapper pgtable: 4k pages, 39-bit VAs, pgdp=0000000080dc4000
+[ 1579.093794] [ffffff8004d76ffe] pgd=180000009ffff003, p4d=180000009ffff003, pud=180000009ffff003, pmd=180000009ffe3003, pte=0060000084d76787
+[ 1579.106343] Internal error: Oops: 000000009600004f [#1] SMP
+[ 1579.193824] CPU: 0 UID: 0 PID: 235 Comm: napi/qdma_eth-3 Tainted: G O 6.12.57 #0
+[ 1579.202614] Tainted: [O]=OOT_MODULE
+[ 1579.206102] Hardware name: Airoha AN7581 Evaluation Board (DT)
+[ 1579.211929] pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
+[ 1579.218889] pc : br_nf_pre_routing_finish_bridge+0x1ac/0xcc8 [br_netfilter]
+[ 1579.225859] lr : br_nf_pre_routing_finish_bridge+0x18c/0xcc8 [br_netfilter]
+[ 1579.232822] sp : ffffffc0817cba20
+[ 1579.236128] x29: ffffffc0817cba20 x28: 0000000000000000 x27: ffffff8002b89000
+[ 1579.243273] x26: ffffff8004d7700e x25: 0000000000000008 x24: 0000000000000000
+[ 1579.250416] x23: ffffffc08179d4c0 x22: 0000000000000000 x21: ffffffc08179d4c0
+[ 1579.257561] x20: ffffff8004d9b800 x19: ffffff8015010000 x18: 0000000000000014
+[ 1579.264704] x17: ffffffbf9e930000 x16: ffffffc0817c8000 x15: 0000000000000070
+[ 1579.271848] x14: 0000000000000080 x13: 0000000000000001 x12: 0000000000000000
+[ 1579.278993] x11: ffffffc0798caae0 x10: ffffff8014db6fd8 x9 : 0000000000000000
+[ 1579.286136] x8 : 0000000000000003 x7 : ffffffc08171f628 x6 : 000000001a3b83d3
+[ 1579.293281] x5 : 0000000000000000 x4 : 1beb76f22fee0000 x3 : ffffff8004d7700e
+[ 1579.300425] x2 : 0000000000000000 x1 : ffffff8004d9b8bc x0 : ffffff80026ed000
+[ 1579.307570] Call trace:
+[ 1579.310018] br_nf_pre_routing_finish_bridge+0x1ac/0xcc8 [br_netfilter]
+[ 1579.316632] br_nf_hook_thresh+0xd4/0x14bc [br_netfilter]
+[ 1579.322032] br_nf_hook_thresh+0x250/0x14bc [br_netfilter]
+[ 1579.327517] br_nf_hook_thresh+0x76c/0x14bc [br_netfilter]
+[ 1579.333003] br_handle_frame+0x180/0x480
+[ 1579.336935] __netif_receive_skb_core.constprop.0+0x540/0xf40
+[ 1579.342682] __netif_receive_skb_one_core+0x28/0x50
+[ 1579.347561] process_backlog+0x98/0x1e0
+[ 1579.351398] __napi_poll+0x34/0x1c4
+[ 1579.354887] net_rx_action+0x178/0x330
+[ 1579.358638] handle_softirqs+0x108/0x2d4
+[ 1579.362560] __do_softirq+0x10/0x18
+[ 1579.366051] ____do_softirq+0xc/0x20
+[ 1579.369627] call_on_irq_stack+0x30/0x4c
+[ 1579.373550] do_softirq_own_stack+0x18/0x20
+[ 1579.377734] do_softirq+0x4c/0x60
+[ 1579.381050] __local_bh_enable_ip+0x88/0x98
+[ 1579.385234] napi_threaded_poll_loop+0x188/0x21c
+[ 1579.389853] napi_threaded_poll+0x70/0x80
+[ 1579.393863] kthread+0xd8/0xdc
+[ 1579.396918] ret_from_fork+0x10/0x20
+[ 1579.400499] Code: 88dffc22 3707ffc2 f9406663 f9406684 (f81f0064)
+[ 1579.406589] ---[ end trace 0000000000000000 ]---
+[ 1579.411209] Kernel panic - not syncing: Oops: Fatal exception in interrupt
+[ 1579.418083] SMP: stopping secondary CPUs
+[ 1579.422012] Kernel Offset: disabled
+
+Fix the issue reallocating the skb headroom if necessary in neigh_hh_bridge routine.
+
+Fixes: e179e6322ac33 ("netfilter: bridge-netfilter: Fix MAC header handling with IP DNAT")
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/neighbour.h | 8 ++++++--
+ net/bridge/br_netfilter_hooks.c | 6 +++++-
+ 2 files changed, 11 insertions(+), 3 deletions(-)
+
+diff --git a/include/net/neighbour.h b/include/net/neighbour.h
+index 93aecfaa7628..b8b385a2a31c 100644
+--- a/include/net/neighbour.h
++++ b/include/net/neighbour.h
+@@ -478,11 +478,15 @@ static inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
+ #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
+ static inline int neigh_hh_bridge(struct hh_cache *hh, struct sk_buff *skb)
+ {
+- unsigned int seq, hh_alen;
++ unsigned int seq, hh_alen = HH_DATA_ALIGN(ETH_HLEN);
++ int err;
++
++ err = skb_cow_head(skb, hh_alen);
++ if (err)
++ return err;
+
+ do {
+ seq = read_seqbegin(&hh->hh_lock);
+- hh_alen = HH_DATA_ALIGN(ETH_HLEN);
+ memcpy(skb->data - hh_alen, hh->hh_data, ETH_ALEN + hh_alen - ETH_HLEN);
+ } while (read_seqretry(&hh->hh_lock, seq));
+ return 0;
+diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c
+index c4765691e781..ffd100a242a0 100644
+--- a/net/bridge/br_netfilter_hooks.c
++++ b/net/bridge/br_netfilter_hooks.c
+@@ -292,7 +292,11 @@ int br_nf_pre_routing_finish_bridge(struct net *net, struct sock *sk, struct sk_
+ goto free_skb;
+ }
+
+- neigh_hh_bridge(&neigh->hh, skb);
++ if (neigh_hh_bridge(&neigh->hh, skb)) {
++ neigh_release(neigh);
++ goto free_skb;
++ }
++
+ skb->dev = br_indev;
+
+ ret = br_handle_frame_finish(net, sk, skb);
+--
+2.53.0
+
mm-damon-core-validate-ranges-in-damon_set_regions.patch
mm-damon-core-disallow-overlapping-input-ranges-for-.patch
netfilter-nf_conntrack_expect-restore-helper-propaga.patch
+netfilter-br_netfilter-reallocate-headroom-if-necess.patch
+net-mpls-initialize-rtm_tos-in-mpls_getroute.patch
+media-uvcvideo-implement-dual-stream-quirk-to-fix-lo.patch
+media-uvcvideo-fix-sequence-number-when-no-eof.patch
--- /dev/null
+From e1cc41fc264d103a19bfebc3fc7133019a7b49c8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 12 Jun 2026 07:09:13 +0800
+Subject: net: airoha: Fix register index for Tx-fwd counter configuration
+
+From: Wayen.Yan <win847@gmail.com>
+
+[ Upstream commit 1402ecccf5630a0b7fa4749d7d2e72abc3f3d73d ]
+
+In airoha_qdma_init_qos_stats(), the Tx-fwd counter configuration
+register uses the same index (i << 1) as the Tx-cpu counter, which
+overwrites the Tx-cpu configuration. The Tx-fwd counter value register
+correctly uses (i << 1) + 1, so the configuration register should use
+the same index.
+
+Fix the REG_CNTR_CFG index from (i << 1) to ((i << 1) + 1) so that
+the Tx-fwd counter is properly configured instead of clobbering the
+Tx-cpu counter config.
+
+Fixes: 20bf7d07c956 ("net: airoha: Add sched ETS offload support")
+Signed-off-by: Wayen.Yan <win847@gmail.com>
+Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Link: https://patch.msgid.link/6a2b40e7.4dd82583.3a5c46.e566@mx.google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/airoha/airoha_eth.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
+index 58e5791e9cd4..9ebc9788ded7 100644
+--- a/drivers/net/ethernet/airoha/airoha_eth.c
++++ b/drivers/net/ethernet/airoha/airoha_eth.c
+@@ -2022,7 +2022,7 @@ static void airoha_qdma_init_qos_stats(struct airoha_qdma *qdma)
+ FIELD_PREP(CNTR_CHAN_MASK, i));
+ /* Tx-fwd transferred count */
+ airoha_qdma_wr(qdma, REG_CNTR_VAL((i << 1) + 1), 0);
+- airoha_qdma_wr(qdma, REG_CNTR_CFG(i << 1),
++ airoha_qdma_wr(qdma, REG_CNTR_CFG((i << 1) + 1),
+ CNTR_EN_MASK | CNTR_ALL_QUEUE_EN_MASK |
+ CNTR_ALL_DSCP_RING_EN_MASK |
+ FIELD_PREP(CNTR_SRC_MASK, 1) |
+--
+2.53.0
+
--- /dev/null
+From 936a49ce377e5e93e23df1ba275802a43312ae10 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jul 2026 10:08:29 +0900
+Subject: net: mpls: initialize rtm_tos in mpls_getroute()
+
+From: Yehyeong Lee <yhlee@isslab.korea.ac.kr>
+
+[ Upstream commit 295dd295e2137e10e9a5b1891d97e0f08de76f03 ]
+
+mpls_getroute() builds the RTM_NEWROUTE reply to an RTM_GETROUTE
+request by filling a struct rtmsg allocated from an skb whose data
+area is not zeroed (alloc_skb(NLMSG_GOODSIZE, ...)). It sets every
+field of the header except rtm_tos:
+
+ r = nlmsg_data(nlh);
+ r->rtm_family = AF_MPLS;
+ r->rtm_dst_len = 20;
+ r->rtm_src_len = 0;
+ r->rtm_table = RT_TABLE_MAIN;
+ r->rtm_type = RTN_UNICAST;
+ r->rtm_scope = RT_SCOPE_UNIVERSE;
+ r->rtm_protocol = rt->rt_protocol;
+ r->rtm_flags = 0;
+
+struct rtmsg has no padding, so the one uninitialised byte rtm_tos
+(offset 3) is copied straight to user space on recvmsg(), leaking a
+byte of uninitialised heap memory. This is in contrast to
+mpls_dump_route(), which fills the very same header and does set
+rtm_tos = 0.
+
+Initialize rtm_tos to 0, matching mpls_dump_route().
+
+Reproduced with KMSAN by adding an MPLS route and issuing a
+non-RTM_F_FIB_MATCH RTM_GETROUTE for its label:
+
+ BUG: KMSAN: kernel-infoleak in _copy_to_iter+0x36c/0x33f0
+ _copy_to_iter+0x36c/0x33f0
+ __skb_datagram_iter+0x196/0x12c0
+ skb_copy_datagram_iter+0x5b/0x210
+ netlink_recvmsg+0x37b/0xef0
+ ...
+ Uninit was created at:
+ __alloc_skb+0x8ca/0x10e0
+ mpls_getroute+0x1280/0x3a40
+ rtnetlink_rcv_msg+0x1138/0x15a0
+ ...
+ Byte 19 of 64 is uninitialized
+
+(byte 19 = nlmsghdr(16) + rtmsg offset 3 = rtm_tos)
+
+Fixes: 397fc9e5cefe ("mpls: route get support")
+Signed-off-by: Yehyeong Lee <yhlee@isslab.korea.ac.kr>
+Link: https://patch.msgid.link/20260723010830.289917-1-yhlee@isslab.korea.ac.kr
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mpls/af_mpls.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
+index 98816e51e01a..0379540d601a 100644
+--- a/net/mpls/af_mpls.c
++++ b/net/mpls/af_mpls.c
+@@ -2468,6 +2468,7 @@ static int mpls_getroute(struct sk_buff *in_skb, struct nlmsghdr *in_nlh,
+ r->rtm_family = AF_MPLS;
+ r->rtm_dst_len = 20;
+ r->rtm_src_len = 0;
++ r->rtm_tos = 0;
+ r->rtm_table = RT_TABLE_MAIN;
+ r->rtm_type = RTN_UNICAST;
+ r->rtm_scope = RT_SCOPE_UNIVERSE;
+--
+2.53.0
+
--- /dev/null
+From 803fa2f613703f2af77704991ad23ea7ae7f1c26 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 May 2026 16:46:38 +0200
+Subject: netfilter: br_netfilter: Reallocate headroom if necessary in
+ neigh_hh_bridge()
+
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+
+[ Upstream commit b2870fc21601db9133bc70c48c603b487614fa3b ]
+
+neigh_hh_bridge() assumes the skb always has sufficient headroom to copy
+the aligned L2 header. This assumption can trigger the crash reported
+below using the following netfilter setup:
+
+$modprobe br_netfilter
+$sysctl -w net.bridge.bridge-nf-call-iptables=1
+
+$root@OpenWrt:~# nft list ruleset
+table ip nat {
+ chain prerouting {
+ type nat hook prerouting priority dstnat; policy accept;
+ ip daddr 192.168.83.123 dnat to 192.168.83.120
+ }
+}
+
+- iperf3 client (192.168.83.119) --> bridge (192.168.83.118) --> iperf3 server (192.168.83.120)
+
+the iperf3 client is sending packet for 192.168.83.123 to the bridge device.
+
+[ 1579.036575] Unable to handle kernel write to read-only memory at virtual address ffffff8004d76ffe
+[ 1579.045482] Mem abort info:
+[ 1579.048273] ESR = 0x000000009600004f
+[ 1579.052024] EC = 0x25: DABT (current EL), IL = 32 bits
+[ 1579.057363] SET = 0, FnV = 0
+[ 1579.060417] EA = 0, S1PTW = 0
+[ 1579.063550] FSC = 0x0f: level 3 permission fault
+[ 1579.068345] Data abort info:
+[ 1579.071224] ISV = 0, ISS = 0x0000004f, ISS2 = 0x00000000
+[ 1579.076720] CM = 0, WnR = 1, TnD = 0, TagAccess = 0
+[ 1579.081770] GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
+[ 1579.087092] swapper pgtable: 4k pages, 39-bit VAs, pgdp=0000000080dc4000
+[ 1579.093794] [ffffff8004d76ffe] pgd=180000009ffff003, p4d=180000009ffff003, pud=180000009ffff003, pmd=180000009ffe3003, pte=0060000084d76787
+[ 1579.106343] Internal error: Oops: 000000009600004f [#1] SMP
+[ 1579.193824] CPU: 0 UID: 0 PID: 235 Comm: napi/qdma_eth-3 Tainted: G O 6.12.57 #0
+[ 1579.202614] Tainted: [O]=OOT_MODULE
+[ 1579.206102] Hardware name: Airoha AN7581 Evaluation Board (DT)
+[ 1579.211929] pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
+[ 1579.218889] pc : br_nf_pre_routing_finish_bridge+0x1ac/0xcc8 [br_netfilter]
+[ 1579.225859] lr : br_nf_pre_routing_finish_bridge+0x18c/0xcc8 [br_netfilter]
+[ 1579.232822] sp : ffffffc0817cba20
+[ 1579.236128] x29: ffffffc0817cba20 x28: 0000000000000000 x27: ffffff8002b89000
+[ 1579.243273] x26: ffffff8004d7700e x25: 0000000000000008 x24: 0000000000000000
+[ 1579.250416] x23: ffffffc08179d4c0 x22: 0000000000000000 x21: ffffffc08179d4c0
+[ 1579.257561] x20: ffffff8004d9b800 x19: ffffff8015010000 x18: 0000000000000014
+[ 1579.264704] x17: ffffffbf9e930000 x16: ffffffc0817c8000 x15: 0000000000000070
+[ 1579.271848] x14: 0000000000000080 x13: 0000000000000001 x12: 0000000000000000
+[ 1579.278993] x11: ffffffc0798caae0 x10: ffffff8014db6fd8 x9 : 0000000000000000
+[ 1579.286136] x8 : 0000000000000003 x7 : ffffffc08171f628 x6 : 000000001a3b83d3
+[ 1579.293281] x5 : 0000000000000000 x4 : 1beb76f22fee0000 x3 : ffffff8004d7700e
+[ 1579.300425] x2 : 0000000000000000 x1 : ffffff8004d9b8bc x0 : ffffff80026ed000
+[ 1579.307570] Call trace:
+[ 1579.310018] br_nf_pre_routing_finish_bridge+0x1ac/0xcc8 [br_netfilter]
+[ 1579.316632] br_nf_hook_thresh+0xd4/0x14bc [br_netfilter]
+[ 1579.322032] br_nf_hook_thresh+0x250/0x14bc [br_netfilter]
+[ 1579.327517] br_nf_hook_thresh+0x76c/0x14bc [br_netfilter]
+[ 1579.333003] br_handle_frame+0x180/0x480
+[ 1579.336935] __netif_receive_skb_core.constprop.0+0x540/0xf40
+[ 1579.342682] __netif_receive_skb_one_core+0x28/0x50
+[ 1579.347561] process_backlog+0x98/0x1e0
+[ 1579.351398] __napi_poll+0x34/0x1c4
+[ 1579.354887] net_rx_action+0x178/0x330
+[ 1579.358638] handle_softirqs+0x108/0x2d4
+[ 1579.362560] __do_softirq+0x10/0x18
+[ 1579.366051] ____do_softirq+0xc/0x20
+[ 1579.369627] call_on_irq_stack+0x30/0x4c
+[ 1579.373550] do_softirq_own_stack+0x18/0x20
+[ 1579.377734] do_softirq+0x4c/0x60
+[ 1579.381050] __local_bh_enable_ip+0x88/0x98
+[ 1579.385234] napi_threaded_poll_loop+0x188/0x21c
+[ 1579.389853] napi_threaded_poll+0x70/0x80
+[ 1579.393863] kthread+0xd8/0xdc
+[ 1579.396918] ret_from_fork+0x10/0x20
+[ 1579.400499] Code: 88dffc22 3707ffc2 f9406663 f9406684 (f81f0064)
+[ 1579.406589] ---[ end trace 0000000000000000 ]---
+[ 1579.411209] Kernel panic - not syncing: Oops: Fatal exception in interrupt
+[ 1579.418083] SMP: stopping secondary CPUs
+[ 1579.422012] Kernel Offset: disabled
+
+Fix the issue reallocating the skb headroom if necessary in neigh_hh_bridge routine.
+
+Fixes: e179e6322ac33 ("netfilter: bridge-netfilter: Fix MAC header handling with IP DNAT")
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/neighbour.h | 8 ++++++--
+ net/bridge/br_netfilter_hooks.c | 6 +++++-
+ 2 files changed, 11 insertions(+), 3 deletions(-)
+
+diff --git a/include/net/neighbour.h b/include/net/neighbour.h
+index cb5f835a5d61..0272d0f0e89d 100644
+--- a/include/net/neighbour.h
++++ b/include/net/neighbour.h
+@@ -476,11 +476,15 @@ static inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
+ #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
+ static inline int neigh_hh_bridge(struct hh_cache *hh, struct sk_buff *skb)
+ {
+- unsigned int seq, hh_alen;
++ unsigned int seq, hh_alen = HH_DATA_ALIGN(ETH_HLEN);
++ int err;
++
++ err = skb_cow_head(skb, hh_alen);
++ if (err)
++ return err;
+
+ do {
+ seq = read_seqbegin(&hh->hh_lock);
+- hh_alen = HH_DATA_ALIGN(ETH_HLEN);
+ memcpy(skb->data - hh_alen, hh->hh_data, ETH_ALEN + hh_alen - ETH_HLEN);
+ } while (read_seqretry(&hh->hh_lock, seq));
+ return 0;
+diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c
+index 5ad3f3ef4ca7..c550907b92dd 100644
+--- a/net/bridge/br_netfilter_hooks.c
++++ b/net/bridge/br_netfilter_hooks.c
+@@ -296,7 +296,11 @@ int br_nf_pre_routing_finish_bridge(struct net *net, struct sock *sk, struct sk_
+ goto free_skb;
+ }
+
+- neigh_hh_bridge(&neigh->hh, skb);
++ if (neigh_hh_bridge(&neigh->hh, skb)) {
++ neigh_release(neigh);
++ goto free_skb;
++ }
++
+ skb->dev = br_indev;
+
+ ret = br_handle_frame_finish(net, sk, skb);
+--
+2.53.0
+
kunit-tool-terminate-kernel-under-test-on-sigint.patch
kunit-tool-skip-stty-when-stdin-is-not-a-tty.patch
um-preserve-errno-within-signal-handler.patch
+netfilter-br_netfilter-reallocate-headroom-if-necess.patch
+net-airoha-fix-register-index-for-tx-fwd-counter-con.patch
+net-mpls-initialize-rtm_tos-in-mpls_getroute.patch
--- /dev/null
+From 081cb57de50473cb058ae07230a580f7d9bbb7ff Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 Jul 2026 19:17:28 +0800
+Subject: drm/gpusvm: publish dpagemap early to avoid device mapping leak on
+ error
+
+From: Honglei Huang <honghuan@amd.com>
+
+commit 7f708f51e3955bda0d77a0b67ab9bea6c97fea99 upstream.
+
+drm_gpusvm_get_pages() only stored the local dpagemap into
+svm_pages->dpagemap on the success path. If a later page failed (e.g.
+-EOPNOTSUPP when ctx->allow_mixed is false) and jumped to err_unmap,
+svm_pages->dpagemap was still NULL, so __drm_gpusvm_unmap_pages() skipped
+device_unmap() and leaked the device mappings already created.
+
+Assign svm_pages->dpagemap when the first device page is mapped so the
+err_unmap path can device_unmap() those mappings.
+
+This issue was found by Sashiko AI review.
+
+Fixes: f70da6f99d4f ("drm/gpusvm: pull out drm_gpusvm_pages substructure")
+Cc: stable@vger.kernel.org
+Reviewed-by: Matthew Brost <matthew.brost@intel.com>
+Signed-off-by: Honglei Huang <honghuan@amd.com>
+Signed-off-by: Matthew Brost <matthew.brost@intel.com>
+Link: https://patch.msgid.link/20260701062800.409248-4-honghuan@amd.com
+[ Adjusted for 6.18.y: drop drm_pagemap_get()/drm_pagemap_put() around the
+ svm_pages->dpagemap assignment; that reference counting is not present in
+ 6.18 where the field is not refcounted (unmap path only clears it). ]
+Signed-off-by: Honglei Huang <honghuan@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/drm_gpusvm.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c
+index 781cd4e5b704..e5c7befe3108 100644
+--- a/drivers/gpu/drm/drm_gpusvm.c
++++ b/drivers/gpu/drm/drm_gpusvm.c
+@@ -1390,6 +1390,14 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
+ err = -EAGAIN;
+ goto err_unmap;
+ }
++
++ /*
++ * Set the dpagemap as soon as the first
++ * device page is mapped so the err_unmap path
++ * can device_unmap() the device mappings that
++ * have already been created.
++ */
++ svm_pages->dpagemap = dpagemap;
+ }
+ svm_pages->dma_addr[j] =
+ dpagemap->ops->device_map(dpagemap,
+@@ -1432,10 +1440,8 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
+ flags.has_dma_mapping = true;
+ }
+
+- if (pagemap) {
++ if (pagemap)
+ flags.has_devmem_pages = true;
+- svm_pages->dpagemap = dpagemap;
+- }
+
+ /* WRITE_ONCE pairs with READ_ONCE for opportunistic checks */
+ WRITE_ONCE(svm_pages->flags.__flags, flags.__flags);
+--
+2.53.0
+
--- /dev/null
+From 725d4c733423508d3690cb930ee44c9d168caa7b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jul 2026 10:08:29 +0900
+Subject: net: mpls: initialize rtm_tos in mpls_getroute()
+
+From: Yehyeong Lee <yhlee@isslab.korea.ac.kr>
+
+[ Upstream commit 295dd295e2137e10e9a5b1891d97e0f08de76f03 ]
+
+mpls_getroute() builds the RTM_NEWROUTE reply to an RTM_GETROUTE
+request by filling a struct rtmsg allocated from an skb whose data
+area is not zeroed (alloc_skb(NLMSG_GOODSIZE, ...)). It sets every
+field of the header except rtm_tos:
+
+ r = nlmsg_data(nlh);
+ r->rtm_family = AF_MPLS;
+ r->rtm_dst_len = 20;
+ r->rtm_src_len = 0;
+ r->rtm_table = RT_TABLE_MAIN;
+ r->rtm_type = RTN_UNICAST;
+ r->rtm_scope = RT_SCOPE_UNIVERSE;
+ r->rtm_protocol = rt->rt_protocol;
+ r->rtm_flags = 0;
+
+struct rtmsg has no padding, so the one uninitialised byte rtm_tos
+(offset 3) is copied straight to user space on recvmsg(), leaking a
+byte of uninitialised heap memory. This is in contrast to
+mpls_dump_route(), which fills the very same header and does set
+rtm_tos = 0.
+
+Initialize rtm_tos to 0, matching mpls_dump_route().
+
+Reproduced with KMSAN by adding an MPLS route and issuing a
+non-RTM_F_FIB_MATCH RTM_GETROUTE for its label:
+
+ BUG: KMSAN: kernel-infoleak in _copy_to_iter+0x36c/0x33f0
+ _copy_to_iter+0x36c/0x33f0
+ __skb_datagram_iter+0x196/0x12c0
+ skb_copy_datagram_iter+0x5b/0x210
+ netlink_recvmsg+0x37b/0xef0
+ ...
+ Uninit was created at:
+ __alloc_skb+0x8ca/0x10e0
+ mpls_getroute+0x1280/0x3a40
+ rtnetlink_rcv_msg+0x1138/0x15a0
+ ...
+ Byte 19 of 64 is uninitialized
+
+(byte 19 = nlmsghdr(16) + rtmsg offset 3 = rtm_tos)
+
+Fixes: 397fc9e5cefe ("mpls: route get support")
+Signed-off-by: Yehyeong Lee <yhlee@isslab.korea.ac.kr>
+Link: https://patch.msgid.link/20260723010830.289917-1-yhlee@isslab.korea.ac.kr
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mpls/af_mpls.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
+index f7f60025d042..f9b8c4d0f049 100644
+--- a/net/mpls/af_mpls.c
++++ b/net/mpls/af_mpls.c
+@@ -2468,6 +2468,7 @@ static int mpls_getroute(struct sk_buff *in_skb, struct nlmsghdr *in_nlh,
+ r->rtm_family = AF_MPLS;
+ r->rtm_dst_len = 20;
+ r->rtm_src_len = 0;
++ r->rtm_tos = 0;
+ r->rtm_table = RT_TABLE_MAIN;
+ r->rtm_type = RTN_UNICAST;
+ r->rtm_scope = RT_SCOPE_UNIVERSE;
+--
+2.53.0
+
--- /dev/null
+From 55d3dc69df3c4c77d98127c4891fe31a2eb9d115 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 May 2026 16:46:38 +0200
+Subject: netfilter: br_netfilter: Reallocate headroom if necessary in
+ neigh_hh_bridge()
+
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+
+[ Upstream commit b2870fc21601db9133bc70c48c603b487614fa3b ]
+
+neigh_hh_bridge() assumes the skb always has sufficient headroom to copy
+the aligned L2 header. This assumption can trigger the crash reported
+below using the following netfilter setup:
+
+$modprobe br_netfilter
+$sysctl -w net.bridge.bridge-nf-call-iptables=1
+
+$root@OpenWrt:~# nft list ruleset
+table ip nat {
+ chain prerouting {
+ type nat hook prerouting priority dstnat; policy accept;
+ ip daddr 192.168.83.123 dnat to 192.168.83.120
+ }
+}
+
+- iperf3 client (192.168.83.119) --> bridge (192.168.83.118) --> iperf3 server (192.168.83.120)
+
+the iperf3 client is sending packet for 192.168.83.123 to the bridge device.
+
+[ 1579.036575] Unable to handle kernel write to read-only memory at virtual address ffffff8004d76ffe
+[ 1579.045482] Mem abort info:
+[ 1579.048273] ESR = 0x000000009600004f
+[ 1579.052024] EC = 0x25: DABT (current EL), IL = 32 bits
+[ 1579.057363] SET = 0, FnV = 0
+[ 1579.060417] EA = 0, S1PTW = 0
+[ 1579.063550] FSC = 0x0f: level 3 permission fault
+[ 1579.068345] Data abort info:
+[ 1579.071224] ISV = 0, ISS = 0x0000004f, ISS2 = 0x00000000
+[ 1579.076720] CM = 0, WnR = 1, TnD = 0, TagAccess = 0
+[ 1579.081770] GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
+[ 1579.087092] swapper pgtable: 4k pages, 39-bit VAs, pgdp=0000000080dc4000
+[ 1579.093794] [ffffff8004d76ffe] pgd=180000009ffff003, p4d=180000009ffff003, pud=180000009ffff003, pmd=180000009ffe3003, pte=0060000084d76787
+[ 1579.106343] Internal error: Oops: 000000009600004f [#1] SMP
+[ 1579.193824] CPU: 0 UID: 0 PID: 235 Comm: napi/qdma_eth-3 Tainted: G O 6.12.57 #0
+[ 1579.202614] Tainted: [O]=OOT_MODULE
+[ 1579.206102] Hardware name: Airoha AN7581 Evaluation Board (DT)
+[ 1579.211929] pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
+[ 1579.218889] pc : br_nf_pre_routing_finish_bridge+0x1ac/0xcc8 [br_netfilter]
+[ 1579.225859] lr : br_nf_pre_routing_finish_bridge+0x18c/0xcc8 [br_netfilter]
+[ 1579.232822] sp : ffffffc0817cba20
+[ 1579.236128] x29: ffffffc0817cba20 x28: 0000000000000000 x27: ffffff8002b89000
+[ 1579.243273] x26: ffffff8004d7700e x25: 0000000000000008 x24: 0000000000000000
+[ 1579.250416] x23: ffffffc08179d4c0 x22: 0000000000000000 x21: ffffffc08179d4c0
+[ 1579.257561] x20: ffffff8004d9b800 x19: ffffff8015010000 x18: 0000000000000014
+[ 1579.264704] x17: ffffffbf9e930000 x16: ffffffc0817c8000 x15: 0000000000000070
+[ 1579.271848] x14: 0000000000000080 x13: 0000000000000001 x12: 0000000000000000
+[ 1579.278993] x11: ffffffc0798caae0 x10: ffffff8014db6fd8 x9 : 0000000000000000
+[ 1579.286136] x8 : 0000000000000003 x7 : ffffffc08171f628 x6 : 000000001a3b83d3
+[ 1579.293281] x5 : 0000000000000000 x4 : 1beb76f22fee0000 x3 : ffffff8004d7700e
+[ 1579.300425] x2 : 0000000000000000 x1 : ffffff8004d9b8bc x0 : ffffff80026ed000
+[ 1579.307570] Call trace:
+[ 1579.310018] br_nf_pre_routing_finish_bridge+0x1ac/0xcc8 [br_netfilter]
+[ 1579.316632] br_nf_hook_thresh+0xd4/0x14bc [br_netfilter]
+[ 1579.322032] br_nf_hook_thresh+0x250/0x14bc [br_netfilter]
+[ 1579.327517] br_nf_hook_thresh+0x76c/0x14bc [br_netfilter]
+[ 1579.333003] br_handle_frame+0x180/0x480
+[ 1579.336935] __netif_receive_skb_core.constprop.0+0x540/0xf40
+[ 1579.342682] __netif_receive_skb_one_core+0x28/0x50
+[ 1579.347561] process_backlog+0x98/0x1e0
+[ 1579.351398] __napi_poll+0x34/0x1c4
+[ 1579.354887] net_rx_action+0x178/0x330
+[ 1579.358638] handle_softirqs+0x108/0x2d4
+[ 1579.362560] __do_softirq+0x10/0x18
+[ 1579.366051] ____do_softirq+0xc/0x20
+[ 1579.369627] call_on_irq_stack+0x30/0x4c
+[ 1579.373550] do_softirq_own_stack+0x18/0x20
+[ 1579.377734] do_softirq+0x4c/0x60
+[ 1579.381050] __local_bh_enable_ip+0x88/0x98
+[ 1579.385234] napi_threaded_poll_loop+0x188/0x21c
+[ 1579.389853] napi_threaded_poll+0x70/0x80
+[ 1579.393863] kthread+0xd8/0xdc
+[ 1579.396918] ret_from_fork+0x10/0x20
+[ 1579.400499] Code: 88dffc22 3707ffc2 f9406663 f9406684 (f81f0064)
+[ 1579.406589] ---[ end trace 0000000000000000 ]---
+[ 1579.411209] Kernel panic - not syncing: Oops: Fatal exception in interrupt
+[ 1579.418083] SMP: stopping secondary CPUs
+[ 1579.422012] Kernel Offset: disabled
+
+Fix the issue reallocating the skb headroom if necessary in neigh_hh_bridge routine.
+
+Fixes: e179e6322ac33 ("netfilter: bridge-netfilter: Fix MAC header handling with IP DNAT")
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/neighbour.h | 8 ++++++--
+ net/bridge/br_netfilter_hooks.c | 6 +++++-
+ 2 files changed, 11 insertions(+), 3 deletions(-)
+
+diff --git a/include/net/neighbour.h b/include/net/neighbour.h
+index 4a30bd458c5a..c13c758aca7e 100644
+--- a/include/net/neighbour.h
++++ b/include/net/neighbour.h
+@@ -480,11 +480,15 @@ static inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
+ #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
+ static inline int neigh_hh_bridge(struct hh_cache *hh, struct sk_buff *skb)
+ {
+- unsigned int seq, hh_alen;
++ unsigned int seq, hh_alen = HH_DATA_ALIGN(ETH_HLEN);
++ int err;
++
++ err = skb_cow_head(skb, hh_alen);
++ if (err)
++ return err;
+
+ do {
+ seq = read_seqbegin(&hh->hh_lock);
+- hh_alen = HH_DATA_ALIGN(ETH_HLEN);
+ memcpy(skb->data - hh_alen, hh->hh_data, ETH_ALEN + hh_alen - ETH_HLEN);
+ } while (read_seqretry(&hh->hh_lock, seq));
+ return 0;
+diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c
+index 083e2fe96441..6544c18febef 100644
+--- a/net/bridge/br_netfilter_hooks.c
++++ b/net/bridge/br_netfilter_hooks.c
+@@ -296,7 +296,11 @@ int br_nf_pre_routing_finish_bridge(struct net *net, struct sock *sk, struct sk_
+ goto free_skb;
+ }
+
+- neigh_hh_bridge(&neigh->hh, skb);
++ if (neigh_hh_bridge(&neigh->hh, skb)) {
++ neigh_release(neigh);
++ goto free_skb;
++ }
++
+ skb->dev = br_indev;
+
+ ret = br_handle_frame_finish(net, sk, skb);
+--
+2.53.0
+
netfilter-nf_conntrack_expect-restore-helper-propaga.patch
kunit-tool-skip-stty-when-stdin-is-not-a-tty.patch
kunit-tool-terminate-kernel-under-test-on-sigint.patch
+netfilter-br_netfilter-reallocate-headroom-if-necess.patch
+net-mpls-initialize-rtm_tos-in-mpls_getroute.patch
+drm-gpusvm-publish-dpagemap-early-to-avoid-device-ma.patch
--- /dev/null
+From af674c2145b8eec73f250be1433796e3af33aba1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jul 2026 10:08:29 +0900
+Subject: net: mpls: initialize rtm_tos in mpls_getroute()
+
+From: Yehyeong Lee <yhlee@isslab.korea.ac.kr>
+
+[ Upstream commit 295dd295e2137e10e9a5b1891d97e0f08de76f03 ]
+
+mpls_getroute() builds the RTM_NEWROUTE reply to an RTM_GETROUTE
+request by filling a struct rtmsg allocated from an skb whose data
+area is not zeroed (alloc_skb(NLMSG_GOODSIZE, ...)). It sets every
+field of the header except rtm_tos:
+
+ r = nlmsg_data(nlh);
+ r->rtm_family = AF_MPLS;
+ r->rtm_dst_len = 20;
+ r->rtm_src_len = 0;
+ r->rtm_table = RT_TABLE_MAIN;
+ r->rtm_type = RTN_UNICAST;
+ r->rtm_scope = RT_SCOPE_UNIVERSE;
+ r->rtm_protocol = rt->rt_protocol;
+ r->rtm_flags = 0;
+
+struct rtmsg has no padding, so the one uninitialised byte rtm_tos
+(offset 3) is copied straight to user space on recvmsg(), leaking a
+byte of uninitialised heap memory. This is in contrast to
+mpls_dump_route(), which fills the very same header and does set
+rtm_tos = 0.
+
+Initialize rtm_tos to 0, matching mpls_dump_route().
+
+Reproduced with KMSAN by adding an MPLS route and issuing a
+non-RTM_F_FIB_MATCH RTM_GETROUTE for its label:
+
+ BUG: KMSAN: kernel-infoleak in _copy_to_iter+0x36c/0x33f0
+ _copy_to_iter+0x36c/0x33f0
+ __skb_datagram_iter+0x196/0x12c0
+ skb_copy_datagram_iter+0x5b/0x210
+ netlink_recvmsg+0x37b/0xef0
+ ...
+ Uninit was created at:
+ __alloc_skb+0x8ca/0x10e0
+ mpls_getroute+0x1280/0x3a40
+ rtnetlink_rcv_msg+0x1138/0x15a0
+ ...
+ Byte 19 of 64 is uninitialized
+
+(byte 19 = nlmsghdr(16) + rtmsg offset 3 = rtm_tos)
+
+Fixes: 397fc9e5cefe ("mpls: route get support")
+Signed-off-by: Yehyeong Lee <yhlee@isslab.korea.ac.kr>
+Link: https://patch.msgid.link/20260723010830.289917-1-yhlee@isslab.korea.ac.kr
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mpls/af_mpls.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
+index 2099ce095edc..cf5ae62ba898 100644
+--- a/net/mpls/af_mpls.c
++++ b/net/mpls/af_mpls.c
+@@ -2469,6 +2469,7 @@ static int mpls_getroute(struct sk_buff *in_skb, struct nlmsghdr *in_nlh,
+ r->rtm_family = AF_MPLS;
+ r->rtm_dst_len = 20;
+ r->rtm_src_len = 0;
++ r->rtm_tos = 0;
+ r->rtm_table = RT_TABLE_MAIN;
+ r->rtm_type = RTN_UNICAST;
+ r->rtm_scope = RT_SCOPE_UNIVERSE;
+--
+2.53.0
+
--- /dev/null
+From 92da9a2759d37369e137570b018903ac0cccf9d6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 May 2026 16:46:38 +0200
+Subject: netfilter: br_netfilter: Reallocate headroom if necessary in
+ neigh_hh_bridge()
+
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+
+[ Upstream commit b2870fc21601db9133bc70c48c603b487614fa3b ]
+
+neigh_hh_bridge() assumes the skb always has sufficient headroom to copy
+the aligned L2 header. This assumption can trigger the crash reported
+below using the following netfilter setup:
+
+$modprobe br_netfilter
+$sysctl -w net.bridge.bridge-nf-call-iptables=1
+
+$root@OpenWrt:~# nft list ruleset
+table ip nat {
+ chain prerouting {
+ type nat hook prerouting priority dstnat; policy accept;
+ ip daddr 192.168.83.123 dnat to 192.168.83.120
+ }
+}
+
+- iperf3 client (192.168.83.119) --> bridge (192.168.83.118) --> iperf3 server (192.168.83.120)
+
+the iperf3 client is sending packet for 192.168.83.123 to the bridge device.
+
+[ 1579.036575] Unable to handle kernel write to read-only memory at virtual address ffffff8004d76ffe
+[ 1579.045482] Mem abort info:
+[ 1579.048273] ESR = 0x000000009600004f
+[ 1579.052024] EC = 0x25: DABT (current EL), IL = 32 bits
+[ 1579.057363] SET = 0, FnV = 0
+[ 1579.060417] EA = 0, S1PTW = 0
+[ 1579.063550] FSC = 0x0f: level 3 permission fault
+[ 1579.068345] Data abort info:
+[ 1579.071224] ISV = 0, ISS = 0x0000004f, ISS2 = 0x00000000
+[ 1579.076720] CM = 0, WnR = 1, TnD = 0, TagAccess = 0
+[ 1579.081770] GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
+[ 1579.087092] swapper pgtable: 4k pages, 39-bit VAs, pgdp=0000000080dc4000
+[ 1579.093794] [ffffff8004d76ffe] pgd=180000009ffff003, p4d=180000009ffff003, pud=180000009ffff003, pmd=180000009ffe3003, pte=0060000084d76787
+[ 1579.106343] Internal error: Oops: 000000009600004f [#1] SMP
+[ 1579.193824] CPU: 0 UID: 0 PID: 235 Comm: napi/qdma_eth-3 Tainted: G O 6.12.57 #0
+[ 1579.202614] Tainted: [O]=OOT_MODULE
+[ 1579.206102] Hardware name: Airoha AN7581 Evaluation Board (DT)
+[ 1579.211929] pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
+[ 1579.218889] pc : br_nf_pre_routing_finish_bridge+0x1ac/0xcc8 [br_netfilter]
+[ 1579.225859] lr : br_nf_pre_routing_finish_bridge+0x18c/0xcc8 [br_netfilter]
+[ 1579.232822] sp : ffffffc0817cba20
+[ 1579.236128] x29: ffffffc0817cba20 x28: 0000000000000000 x27: ffffff8002b89000
+[ 1579.243273] x26: ffffff8004d7700e x25: 0000000000000008 x24: 0000000000000000
+[ 1579.250416] x23: ffffffc08179d4c0 x22: 0000000000000000 x21: ffffffc08179d4c0
+[ 1579.257561] x20: ffffff8004d9b800 x19: ffffff8015010000 x18: 0000000000000014
+[ 1579.264704] x17: ffffffbf9e930000 x16: ffffffc0817c8000 x15: 0000000000000070
+[ 1579.271848] x14: 0000000000000080 x13: 0000000000000001 x12: 0000000000000000
+[ 1579.278993] x11: ffffffc0798caae0 x10: ffffff8014db6fd8 x9 : 0000000000000000
+[ 1579.286136] x8 : 0000000000000003 x7 : ffffffc08171f628 x6 : 000000001a3b83d3
+[ 1579.293281] x5 : 0000000000000000 x4 : 1beb76f22fee0000 x3 : ffffff8004d7700e
+[ 1579.300425] x2 : 0000000000000000 x1 : ffffff8004d9b8bc x0 : ffffff80026ed000
+[ 1579.307570] Call trace:
+[ 1579.310018] br_nf_pre_routing_finish_bridge+0x1ac/0xcc8 [br_netfilter]
+[ 1579.316632] br_nf_hook_thresh+0xd4/0x14bc [br_netfilter]
+[ 1579.322032] br_nf_hook_thresh+0x250/0x14bc [br_netfilter]
+[ 1579.327517] br_nf_hook_thresh+0x76c/0x14bc [br_netfilter]
+[ 1579.333003] br_handle_frame+0x180/0x480
+[ 1579.336935] __netif_receive_skb_core.constprop.0+0x540/0xf40
+[ 1579.342682] __netif_receive_skb_one_core+0x28/0x50
+[ 1579.347561] process_backlog+0x98/0x1e0
+[ 1579.351398] __napi_poll+0x34/0x1c4
+[ 1579.354887] net_rx_action+0x178/0x330
+[ 1579.358638] handle_softirqs+0x108/0x2d4
+[ 1579.362560] __do_softirq+0x10/0x18
+[ 1579.366051] ____do_softirq+0xc/0x20
+[ 1579.369627] call_on_irq_stack+0x30/0x4c
+[ 1579.373550] do_softirq_own_stack+0x18/0x20
+[ 1579.377734] do_softirq+0x4c/0x60
+[ 1579.381050] __local_bh_enable_ip+0x88/0x98
+[ 1579.385234] napi_threaded_poll_loop+0x188/0x21c
+[ 1579.389853] napi_threaded_poll+0x70/0x80
+[ 1579.393863] kthread+0xd8/0xdc
+[ 1579.396918] ret_from_fork+0x10/0x20
+[ 1579.400499] Code: 88dffc22 3707ffc2 f9406663 f9406684 (f81f0064)
+[ 1579.406589] ---[ end trace 0000000000000000 ]---
+[ 1579.411209] Kernel panic - not syncing: Oops: Fatal exception in interrupt
+[ 1579.418083] SMP: stopping secondary CPUs
+[ 1579.422012] Kernel Offset: disabled
+
+Fix the issue reallocating the skb headroom if necessary in neigh_hh_bridge routine.
+
+Fixes: e179e6322ac33 ("netfilter: bridge-netfilter: Fix MAC header handling with IP DNAT")
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/neighbour.h | 8 ++++++--
+ net/bridge/br_netfilter_hooks.c | 6 +++++-
+ 2 files changed, 11 insertions(+), 3 deletions(-)
+
+diff --git a/include/net/neighbour.h b/include/net/neighbour.h
+index d775906a65c7..9ada7451fd2a 100644
+--- a/include/net/neighbour.h
++++ b/include/net/neighbour.h
+@@ -476,11 +476,15 @@ static inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
+ #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
+ static inline int neigh_hh_bridge(struct hh_cache *hh, struct sk_buff *skb)
+ {
+- unsigned int seq, hh_alen;
++ unsigned int seq, hh_alen = HH_DATA_ALIGN(ETH_HLEN);
++ int err;
++
++ err = skb_cow_head(skb, hh_alen);
++ if (err)
++ return err;
+
+ do {
+ seq = read_seqbegin(&hh->hh_lock);
+- hh_alen = HH_DATA_ALIGN(ETH_HLEN);
+ memcpy(skb->data - hh_alen, hh->hh_data, ETH_ALEN + hh_alen - ETH_HLEN);
+ } while (read_seqretry(&hh->hh_lock, seq));
+ return 0;
+diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c
+index e6962d693359..3fbcf1b7e93d 100644
+--- a/net/bridge/br_netfilter_hooks.c
++++ b/net/bridge/br_netfilter_hooks.c
+@@ -292,7 +292,11 @@ int br_nf_pre_routing_finish_bridge(struct net *net, struct sock *sk, struct sk_
+ goto free_skb;
+ }
+
+- neigh_hh_bridge(&neigh->hh, skb);
++ if (neigh_hh_bridge(&neigh->hh, skb)) {
++ neigh_release(neigh);
++ goto free_skb;
++ }
++
+ skb->dev = br_indev;
+
+ ret = br_handle_frame_finish(net, sk, skb);
+--
+2.53.0
+
netfilter-nf_conntrack_expect-restore-helper-propaga.patch
+netfilter-br_netfilter-reallocate-headroom-if-necess.patch
+net-mpls-initialize-rtm_tos-in-mpls_getroute.patch
--- /dev/null
+From 7426b5daf78256a507e3d6bc16375a9ad27dc735 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jul 2026 10:08:29 +0900
+Subject: net: mpls: initialize rtm_tos in mpls_getroute()
+
+From: Yehyeong Lee <yhlee@isslab.korea.ac.kr>
+
+[ Upstream commit 295dd295e2137e10e9a5b1891d97e0f08de76f03 ]
+
+mpls_getroute() builds the RTM_NEWROUTE reply to an RTM_GETROUTE
+request by filling a struct rtmsg allocated from an skb whose data
+area is not zeroed (alloc_skb(NLMSG_GOODSIZE, ...)). It sets every
+field of the header except rtm_tos:
+
+ r = nlmsg_data(nlh);
+ r->rtm_family = AF_MPLS;
+ r->rtm_dst_len = 20;
+ r->rtm_src_len = 0;
+ r->rtm_table = RT_TABLE_MAIN;
+ r->rtm_type = RTN_UNICAST;
+ r->rtm_scope = RT_SCOPE_UNIVERSE;
+ r->rtm_protocol = rt->rt_protocol;
+ r->rtm_flags = 0;
+
+struct rtmsg has no padding, so the one uninitialised byte rtm_tos
+(offset 3) is copied straight to user space on recvmsg(), leaking a
+byte of uninitialised heap memory. This is in contrast to
+mpls_dump_route(), which fills the very same header and does set
+rtm_tos = 0.
+
+Initialize rtm_tos to 0, matching mpls_dump_route().
+
+Reproduced with KMSAN by adding an MPLS route and issuing a
+non-RTM_F_FIB_MATCH RTM_GETROUTE for its label:
+
+ BUG: KMSAN: kernel-infoleak in _copy_to_iter+0x36c/0x33f0
+ _copy_to_iter+0x36c/0x33f0
+ __skb_datagram_iter+0x196/0x12c0
+ skb_copy_datagram_iter+0x5b/0x210
+ netlink_recvmsg+0x37b/0xef0
+ ...
+ Uninit was created at:
+ __alloc_skb+0x8ca/0x10e0
+ mpls_getroute+0x1280/0x3a40
+ rtnetlink_rcv_msg+0x1138/0x15a0
+ ...
+ Byte 19 of 64 is uninitialized
+
+(byte 19 = nlmsghdr(16) + rtmsg offset 3 = rtm_tos)
+
+Fixes: 397fc9e5cefe ("mpls: route get support")
+Signed-off-by: Yehyeong Lee <yhlee@isslab.korea.ac.kr>
+Link: https://patch.msgid.link/20260723010830.289917-1-yhlee@isslab.korea.ac.kr
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mpls/af_mpls.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
+index 35069183f59c..1ad5a2d9b6cd 100644
+--- a/net/mpls/af_mpls.c
++++ b/net/mpls/af_mpls.c
+@@ -2541,6 +2541,7 @@ static int mpls_getroute(struct sk_buff *in_skb, struct nlmsghdr *in_nlh,
+ r->rtm_family = AF_MPLS;
+ r->rtm_dst_len = 20;
+ r->rtm_src_len = 0;
++ r->rtm_tos = 0;
+ r->rtm_table = RT_TABLE_MAIN;
+ r->rtm_type = RTN_UNICAST;
+ r->rtm_scope = RT_SCOPE_UNIVERSE;
+--
+2.53.0
+
--- /dev/null
+net-mpls-initialize-rtm_tos-in-mpls_getroute.patch