FAILED: patch "[PATCH] media: omap3isp: Use struct_group() for memcpy() region" failed to apply to 5.10-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 5.10-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 <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From d4568fc8525897e683983806f813be1ae9eedaed Mon Sep 17 00:00:00 2001
From: Kees Cook <[email protected]>
Date: Mon, 24 Jan 2022 18:29:52 +0100
Subject: [PATCH] media: omap3isp: Use struct_group() for memcpy() region
In preparation for FORTIFY_SOURCE performing compile-time and run-time field bounds checking for memcpy(), memmove(), and memset(), avoid intentionally writing across neighboring fields. Wrap the target region in struct_group(). This additionally fixes a theoretical misalignment of the copy (since the size of "buf" changes between 64-bit and 32-bit, but this is likely never built for 64-bit).
FWIW, I think this code is totally broken on 64-bit (which appears to not be a "real" build configuration): it would either always fail (with an uninitialized data->buf_size) or would cause corruption in userspace due to the copy_to_user() in the call path against an uninitialized data->buf value:
omap3isp_stat_request_statistics_time32(...)
struct omap3isp_stat_data data64;
...
omap3isp_stat_request_statistics(stat, &data64);int omap3isp_stat_request_statistics(struct ispstat *stat,
struct omap3isp_stat_data *data)
...
buf = isp_stat_buf_get(stat, data);static struct ispstat_buffer *isp_stat_buf_get(struct ispstat *stat,
struct omap3isp_stat_data *data)
...
if (buf->buf_size > data->buf_size) {
...
return ERR_PTR(-EINVAL);
}
...
rval = copy_to_user(data->buf,
buf->virt_addr,
buf->buf_size);Regardless, additionally initialize data64 to be zero-filled to avoid undefined behavior.
drivers/media/platform/omap3isp/ispstat.c +3 -2
@@ -512,7 +512,7 @@ int omap3isp_stat_request_statistics(struct ispstat *stat,int omap3isp_stat_request_statistics_time32 (struct ispstat *stat,struct omap3isp_stat_data_time32 *data) { -struct omap3isp_stat_data data64; +struct omap3isp_stat_data data64 = { };int ret; ret =omap3isp_stat_request_statistics (stat, &data64);
@@ -521,7 +521,8 @@ int omap3isp_stat_request_statistics_time32(struct ispstat *stat, data->ts.tv_sec = data64.ts.tv_sec; data->ts.tv_usec = data64.ts.tv_usec; -memcpy (&data->buf, &data64.buf,sizeof (*data) -sizeof (data->ts)); + data->buf = (uintptr_t )data64.buf; +memcpy (&data->frame, &data64.frame,sizeof (data->frame));return 0 ; }
include/uapi/linux/omap3isp.h +13 -8
@@ -162,6 +162,7 @@ struct omap3isp_h3a_aewb_config {* struct omap3isp_stat_data - Statistic data sent to or received from user * @ts: Timestamp of returned framestats. * @buf: Pointer to pass to user. +* @buf_size: Size of buffer. * @frame_number: Frame number of requested stats. * @cur_frame: Current frame number being processed. * @config_counter: Number of the configuration associated with the data.
@@ -176,10 +177,12 @@ struct omap3isp_stat_data {struct timeval ts;#endif void __user *buf; -__u32 buf_size; -__u16 frame_number; -__u16 cur_frame; -__u16 config_counter; + __struct_group(/* no tag */, frame, /* no attrs */, + __u32 buf_size; +__u16 frame_number; +__u16 cur_frame; +__u16 config_counter; + ); };#ifdef __KERNEL__
@@ -189,10 +192,12 @@ struct omap3isp_stat_data_time32 {__s32 tv_usec; } ts;__u32 buf; -__u32 buf_size; -__u16 frame_number; -__u16 cur_frame; -__u16 config_counter; + __struct_group(/* no tag */, frame, /* no attrs */, + __u32 buf_size; +__u16 frame_number; +__u16 cur_frame; +__u16 config_counter; + ); };#endif