From 476ddf3b04af1f3171c9e550c8a619ec460481ff Mon Sep 17 00:00:00 2001 From: changtao Date: Thu, 17 Oct 2024 19:50:35 +0800 Subject: [PATCH] fix CVE-2024-5171 --- ...r-overflows-in-align_image_dimension.patch | 218 ++++++++++++++++++ ...overflows-in-calc-of-stride_in_bytes.patch | 76 ++++++ aom.spec | 8 +- 3 files changed, 301 insertions(+), 1 deletion(-) create mode 100644 Avoid-integer-overflows-in-align_image_dimension.patch create mode 100644 Fix-integer-overflows-in-calc-of-stride_in_bytes.patch diff --git a/Avoid-integer-overflows-in-align_image_dimension.patch b/Avoid-integer-overflows-in-align_image_dimension.patch new file mode 100644 index 0000000..8d12770 --- /dev/null +++ b/Avoid-integer-overflows-in-align_image_dimension.patch @@ -0,0 +1,218 @@ +From 8156fb76d88845d716867d20333fd27001be47a8 Mon Sep 17 00:00:00 2001 +From: Wan-Teh Chang +Date: Thu, 17 Oct 2024 19:39:48 +0800 +Subject: [PATCH 2/2] Avoid integer overflows in align_image_dimension() + +Impose maximum values on the input parameters so that we can perform +arithmetic operations without worrying about overflows. + +Fix a bug (introduced in commit 7aa2edc) that the ~ operator is applied +to (stride_align - 1), which is unsigned int, and then the result is +converted to uint64_t. + +Also change the AomImageTest.AomImgAllocHugeWidth test to write to the +first and last samples in the first row of the Y plane, so that the test +will crash if there is unsigned integer overflow in the calculation of +stride_in_bytes. + +Bug: chromium:332382766 +Change-Id: I634c38c35a296b5bbf3de7ddf10040e7ec5ee9a1 +(cherry picked from commit 60653dff7f8ee3e769a0aeec5e210a4fc2687717) +--- + ...overflows-in-calc-of-stride_in_bytes.patch | 76 +++++++++++++++++++ + aom/aom_image.h | 28 ++++--- + aom/src/aom_image.c | 21 +++-- + 3 files changed, 110 insertions(+), 15 deletions(-) + create mode 100644 Fix-integer-overflows-in-calc-of-stride_in_bytes.patch + +diff --git a/Fix-integer-overflows-in-calc-of-stride_in_bytes.patch b/Fix-integer-overflows-in-calc-of-stride_in_bytes.patch +new file mode 100644 +index 0000000..3fbd697 +--- /dev/null ++++ b/Fix-integer-overflows-in-calc-of-stride_in_bytes.patch +@@ -0,0 +1,76 @@ ++From 19d9966572a410804349e1a8ee2017fed49a6dab Mon Sep 17 00:00:00 2001 ++From: Wan-Teh Chang ++Date: Thu, 17 Oct 2024 19:15:45 +0800 ++Subject: [PATCH 1/2] Fix integer overflows in calc of stride_in_bytes ++ ++Fix unsigned integer overflows in the calculation of stride_in_bytes in ++img_alloc_helper() when d_w is huge. ++ ++Change the type of stride_in_bytes from unsigned int to int because it ++will be assigned to img->stride[AOM_PLANE_Y], which is of the int type. ++ ++Test: ++cmake ../aom -G Ninja -DCMAKE_C_COMPILER=clang \ ++ -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Debug \ ++ -DSANITIZE=unsigned-integer-overflow ++ninja ++./test_libaom --gtest_filter=AomImageTest.AomImgAllocHugeWidth ++ ++Bug: chromium:332382766 ++Change-Id: Iaccb83bcd13ddc3ea5e6f01da91bb01215ddb461 ++(cherry picked from commit 7aa2edc2b09f98c32820923d813fd73eb23b5861) ++ ++--- ++ aom/src/aom_image.c | 14 +++++++------- ++ 1 file changed, 7 insertions(+), 7 deletions(-) ++ ++diff --git a/aom/src/aom_image.c b/aom/src/aom_image.c ++index f703504..130eeea 100644 ++--- a/aom/src/aom_image.c +++++ b/aom/src/aom_image.c ++@@ -35,9 +35,7 @@ static aom_image_t *img_alloc_helper( ++ /* NOTE: In this function, bit_depth is either 8 or 16 (if ++ * AOM_IMG_FMT_HIGHBITDEPTH is set), never 10 or 12. ++ */ ++- unsigned int h, w, s, xcs, ycs, bps, bit_depth; ++- unsigned int stride_in_bytes; ++- +++ unsigned int h, w, xcs, ycs, bps, bit_depth; ++ /* Treat align==0 like align==1 */ ++ if (!buf_align) buf_align = 1; ++ ++@@ -100,9 +98,11 @@ static aom_image_t *img_alloc_helper( ++ w = align_image_dimension(d_w, xcs, size_align); ++ h = align_image_dimension(d_h, ycs, size_align); ++ ++- s = (fmt & AOM_IMG_FMT_PLANAR) ? w : bps * w / bit_depth; +++ uint64_t s = (fmt & AOM_IMG_FMT_PLANAR) ? w : (uint64_t)bps * w / bit_depth; ++ s = (s + 2 * border + stride_align - 1) & ~(stride_align - 1); ++- stride_in_bytes = s * bit_depth / 8; +++ s = s * bit_depth / 8; +++ if (s > INT_MAX) goto fail; +++ const int stride_in_bytes = (int)s; ++ ++ /* Allocate the new image */ ++ if (!img) { ++@@ -220,7 +220,7 @@ int aom_img_set_rect(aom_image_t *img, unsigned int x, unsigned int y, ++ ++ img->planes[AOM_PLANE_Y] = ++ data + x * bytes_per_sample + y * img->stride[AOM_PLANE_Y]; ++- data += (img->h + 2 * border) * img->stride[AOM_PLANE_Y]; +++ data += ((size_t)img->h + 2 * border) * img->stride[AOM_PLANE_Y]; ++ ++ unsigned int uv_border_h = border >> img->y_chroma_shift; ++ unsigned int uv_x = x >> img->x_chroma_shift; ++@@ -235,7 +235,7 @@ int aom_img_set_rect(aom_image_t *img, unsigned int x, unsigned int y, ++ } else { ++ img->planes[AOM_PLANE_V] = ++ data + uv_x * bytes_per_sample + uv_y * img->stride[AOM_PLANE_V]; ++- data += ((img->h >> img->y_chroma_shift) + 2 * uv_border_h) * +++ data += ((size_t)(img->h >> img->y_chroma_shift) + 2 * uv_border_h) * ++ img->stride[AOM_PLANE_V]; ++ img->planes[AOM_PLANE_U] = ++ data + uv_x * bytes_per_sample + uv_y * img->stride[AOM_PLANE_U]; ++-- ++2.43.0 ++ +diff --git a/aom/aom_image.h b/aom/aom_image.h +index 5f615d7..abb5bff 100644 +--- a/aom/aom_image.h ++++ b/aom/aom_image.h +@@ -208,10 +208,13 @@ typedef struct aom_image_rect { + * is NULL, the storage for the descriptor will be + * allocated on the heap. + * \param[in] fmt Format for the image +- * \param[in] d_w Width of the image +- * \param[in] d_h Height of the image ++ * \param[in] d_w Width of the image. Must not exceed 0x08000000 ++ * (2^27). ++ * \param[in] d_h Height of the image. Must not exceed 0x08000000 ++ * (2^27). + * \param[in] align Alignment, in bytes, of the image buffer and +- * each row in the image (stride). ++ * each row in the image (stride). Must not exceed ++ * 65536. + * + * \return Returns a pointer to the initialized image descriptor. If the img + * parameter is non-null, the value of the img parameter will be +@@ -231,10 +234,12 @@ aom_image_t *aom_img_alloc(aom_image_t *img, aom_img_fmt_t fmt, + * is NULL, the storage for the descriptor will be + * allocated on the heap. + * \param[in] fmt Format for the image +- * \param[in] d_w Width of the image +- * \param[in] d_h Height of the image ++ * \param[in] d_w Width of the image. Must not exceed 0x08000000 ++ * (2^27). ++ * \param[in] d_h Height of the image. Must not exceed 0x08000000 ++ * + * \param[in] align Alignment, in bytes, of each row in the image +- * (stride). ++ * (stride).Must not exceed 65536. + * \param[in] img_data Storage to use for the image + * + * \return Returns a pointer to the initialized image descriptor. If the img +@@ -255,13 +260,16 @@ aom_image_t *aom_img_wrap(aom_image_t *img, aom_img_fmt_t fmt, unsigned int d_w, + * is NULL, the storage for the descriptor will be + * allocated on the heap. + * \param[in] fmt Format for the image +- * \param[in] d_w Width of the image +- * \param[in] d_h Height of the image ++ * (2^27). ++ * \param[in] d_h Height of the image. Must not exceed 0x08000000 ++ * (2^27). + * \param[in] align Alignment, in bytes, of the image buffer and +- * each row in the image (stride). ++ * each row in the image (stride). Must not exceed ++ * 65536. + * \param[in] size_align Alignment, in pixels, of the image width and height. ++ * Must not exceed 65536. + * \param[in] border A border that is padded on four sides of the image. +- * ++ * Must not exceed 65536. + * \return Returns a pointer to the initialized image descriptor. If the img + * parameter is non-null, the value of the img parameter will be + * returned. +diff --git a/aom/src/aom_image.c b/aom/src/aom_image.c +index 130eeea..31fafa6 100644 +--- a/aom/src/aom_image.c ++++ b/aom/src/aom_image.c +@@ -8,7 +8,7 @@ + * Media Patent License 1.0 was not distributed with this source code in the + * PATENTS file, you can obtain it at www.aomedia.org/license/patent. + */ +- ++#include + #include + #include + +@@ -35,7 +35,16 @@ static aom_image_t *img_alloc_helper( + /* NOTE: In this function, bit_depth is either 8 or 16 (if + * AOM_IMG_FMT_HIGHBITDEPTH is set), never 10 or 12. + */ +- unsigned int h, w, xcs, ycs, bps, bit_depth; ++ unsigned int xcs, ycs, bps, bit_depth; ++ ++ /* Impose maximum values on input parameters so that this function can ++ * perform arithmetic operations without worrying about overflows. ++ */ ++ if (d_w > 0x08000000 || d_h > 0x08000000 || buf_align > 65536 || ++ stride_align > 65536 || size_align > 65536 || border > 65536) { ++ goto fail; ++ } ++ + /* Treat align==0 like align==1 */ + if (!buf_align) buf_align = 1; + +@@ -95,11 +104,13 @@ static aom_image_t *img_alloc_helper( + } + + /* Calculate storage sizes given the chroma subsampling */ +- w = align_image_dimension(d_w, xcs, size_align); +- h = align_image_dimension(d_h, ycs, size_align); ++ const unsigned int w = align_image_dimension(d_w, xcs, size_align); ++ assert(d_w <= w); ++ const unsigned int h = align_image_dimension(d_h, ycs, size_align); ++ assert(d_h <= h); + + uint64_t s = (fmt & AOM_IMG_FMT_PLANAR) ? w : (uint64_t)bps * w / bit_depth; +- s = (s + 2 * border + stride_align - 1) & ~(stride_align - 1); ++ s = (s + 2 * border + stride_align - 1) & ~((uint64_t)stride_align - 1); + s = s * bit_depth / 8; + if (s > INT_MAX) goto fail; + const int stride_in_bytes = (int)s; +-- +2.43.0 + diff --git a/Fix-integer-overflows-in-calc-of-stride_in_bytes.patch b/Fix-integer-overflows-in-calc-of-stride_in_bytes.patch new file mode 100644 index 0000000..3fbd697 --- /dev/null +++ b/Fix-integer-overflows-in-calc-of-stride_in_bytes.patch @@ -0,0 +1,76 @@ +From 19d9966572a410804349e1a8ee2017fed49a6dab Mon Sep 17 00:00:00 2001 +From: Wan-Teh Chang +Date: Thu, 17 Oct 2024 19:15:45 +0800 +Subject: [PATCH 1/2] Fix integer overflows in calc of stride_in_bytes + +Fix unsigned integer overflows in the calculation of stride_in_bytes in +img_alloc_helper() when d_w is huge. + +Change the type of stride_in_bytes from unsigned int to int because it +will be assigned to img->stride[AOM_PLANE_Y], which is of the int type. + +Test: +cmake ../aom -G Ninja -DCMAKE_C_COMPILER=clang \ + -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Debug \ + -DSANITIZE=unsigned-integer-overflow +ninja +./test_libaom --gtest_filter=AomImageTest.AomImgAllocHugeWidth + +Bug: chromium:332382766 +Change-Id: Iaccb83bcd13ddc3ea5e6f01da91bb01215ddb461 +(cherry picked from commit 7aa2edc2b09f98c32820923d813fd73eb23b5861) + +--- + aom/src/aom_image.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/aom/src/aom_image.c b/aom/src/aom_image.c +index f703504..130eeea 100644 +--- a/aom/src/aom_image.c ++++ b/aom/src/aom_image.c +@@ -35,9 +35,7 @@ static aom_image_t *img_alloc_helper( + /* NOTE: In this function, bit_depth is either 8 or 16 (if + * AOM_IMG_FMT_HIGHBITDEPTH is set), never 10 or 12. + */ +- unsigned int h, w, s, xcs, ycs, bps, bit_depth; +- unsigned int stride_in_bytes; +- ++ unsigned int h, w, xcs, ycs, bps, bit_depth; + /* Treat align==0 like align==1 */ + if (!buf_align) buf_align = 1; + +@@ -100,9 +98,11 @@ static aom_image_t *img_alloc_helper( + w = align_image_dimension(d_w, xcs, size_align); + h = align_image_dimension(d_h, ycs, size_align); + +- s = (fmt & AOM_IMG_FMT_PLANAR) ? w : bps * w / bit_depth; ++ uint64_t s = (fmt & AOM_IMG_FMT_PLANAR) ? w : (uint64_t)bps * w / bit_depth; + s = (s + 2 * border + stride_align - 1) & ~(stride_align - 1); +- stride_in_bytes = s * bit_depth / 8; ++ s = s * bit_depth / 8; ++ if (s > INT_MAX) goto fail; ++ const int stride_in_bytes = (int)s; + + /* Allocate the new image */ + if (!img) { +@@ -220,7 +220,7 @@ int aom_img_set_rect(aom_image_t *img, unsigned int x, unsigned int y, + + img->planes[AOM_PLANE_Y] = + data + x * bytes_per_sample + y * img->stride[AOM_PLANE_Y]; +- data += (img->h + 2 * border) * img->stride[AOM_PLANE_Y]; ++ data += ((size_t)img->h + 2 * border) * img->stride[AOM_PLANE_Y]; + + unsigned int uv_border_h = border >> img->y_chroma_shift; + unsigned int uv_x = x >> img->x_chroma_shift; +@@ -235,7 +235,7 @@ int aom_img_set_rect(aom_image_t *img, unsigned int x, unsigned int y, + } else { + img->planes[AOM_PLANE_V] = + data + uv_x * bytes_per_sample + uv_y * img->stride[AOM_PLANE_V]; +- data += ((img->h >> img->y_chroma_shift) + 2 * uv_border_h) * ++ data += ((size_t)(img->h >> img->y_chroma_shift) + 2 * uv_border_h) * + img->stride[AOM_PLANE_V]; + img->planes[AOM_PLANE_U] = + data + uv_x * bytes_per_sample + uv_y * img->stride[AOM_PLANE_U]; +-- +2.43.0 + diff --git a/aom.spec b/aom.spec index f55c86f..3f4554b 100644 --- a/aom.spec +++ b/aom.spec @@ -10,13 +10,16 @@ Name: aom Version: 1.0.0 -Release: 1 +Release: 2 Summary: Royalty-free next-generation video format License: BSD URL: http://aomedia.org/ Source0: https://aomedia.googlesource.com/%{name}/+archive/%{commit}.tar.gz#/%{name}-%{shortcommit}.tar.gz +Patch01: Fix-integer-overflows-in-calc-of-stride_in_bytes.patch +Patch02: Avoid-integer-overflows-in-align_image_dimension.patch + BuildRequires: gcc-c++ gcc cmake3 BuildRequires: doxygen git-core graphviz BuildRequires: perl-interpreter perl(Getopt::Long) perl-interpreter python3-devel yasm @@ -93,5 +96,8 @@ cd _build %{_libdir}/pkgconfig/%{name}.pc %changelog +* Thu Oct 17 2024 changtao - 1.0.0-2 +- fix CVE-2024-5171 + * Fri May 07 2021 weidong - 1.0.0-1 - Initial package. -- Gitee