diff options
Diffstat (limited to 'meta')
3 files changed, 225 insertions, 0 deletions
diff --git a/meta/recipes-multimedia/libpng/files/CVE-2025-65018-01.patch b/meta/recipes-multimedia/libpng/files/CVE-2025-65018-01.patch new file mode 100644 index 0000000000..cdee6c76c0 --- /dev/null +++ b/meta/recipes-multimedia/libpng/files/CVE-2025-65018-01.patch | |||
| @@ -0,0 +1,60 @@ | |||
| 1 | From 16b5e3823918840aae65c0a6da57c78a5a496a4d Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Cosmin Truta <ctruta@gmail.com> | ||
| 3 | Date: Mon, 17 Nov 2025 20:38:47 +0200 | ||
| 4 | Subject: [PATCH] Fix a buffer overflow in `png_image_finish_read` | ||
| 5 | MIME-Version: 1.0 | ||
| 6 | Content-Type: text/plain; charset=UTF-8 | ||
| 7 | Content-Transfer-Encoding: 8bit | ||
| 8 | |||
| 9 | Reject bit-depth mismatches between IHDR and the requested output | ||
| 10 | format. When a 16-bit PNG is processed with an 8-bit output format | ||
| 11 | request, `png_combine_row` writes using the IHDR depth before | ||
| 12 | transformation, causing writes beyond the buffer allocated via | ||
| 13 | `PNG_IMAGE_SIZE(image)`. | ||
| 14 | |||
| 15 | The validation establishes a safe API contract where | ||
| 16 | `PNG_IMAGE_SIZE(image)` is guaranteed to be sufficient across the | ||
| 17 | transformation pipeline. | ||
| 18 | |||
| 19 | Example overflow (32×32 pixels, 16-bit RGB to 8-bit RGBA): | ||
| 20 | - Input format: 16 bits/channel × 3 channels = 6144 bytes | ||
| 21 | - Output buffer: 8 bits/channel × 4 channels = 4096 bytes | ||
| 22 | - Overflow: 6144 bytes - 4096 bytes = 2048 bytes | ||
| 23 | |||
| 24 | Larger images produce proportionally larger overflows. For example, | ||
| 25 | for 256×256 pixels, the overflow is 131072 bytes. | ||
| 26 | |||
| 27 | Reported-by: yosiimich <yosiimich@users.noreply.github.com> | ||
| 28 | |||
| 29 | CVE: CVE-2025-65018 | ||
| 30 | Upstream-Status: Backport [https://github.com/pnggroup/libpng/commit/16b5e3823918840aae65c0a6da57c78a5a496a4d] | ||
| 31 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
| 32 | --- | ||
| 33 | pngread.c | 14 ++++++++++++++ | ||
| 34 | 1 file changed, 14 insertions(+) | ||
| 35 | |||
| 36 | diff --git a/pngread.c b/pngread.c | ||
| 37 | index 212afb7d2..92571ec33 100644 | ||
| 38 | --- a/pngread.c | ||
| 39 | +++ b/pngread.c | ||
| 40 | @@ -4166,6 +4166,20 @@ png_image_finish_read(png_imagep image, png_const_colorp background, | ||
| 41 | int result; | ||
| 42 | png_image_read_control display; | ||
| 43 | |||
| 44 | + /* Reject bit depth mismatches to avoid buffer overflows. */ | ||
| 45 | + png_uint_32 ihdr_bit_depth = | ||
| 46 | + image->opaque->png_ptr->bit_depth; | ||
| 47 | + int requested_linear = | ||
| 48 | + (image->format & PNG_FORMAT_FLAG_LINEAR) != 0; | ||
| 49 | + if (ihdr_bit_depth == 16 && !requested_linear) | ||
| 50 | + return png_image_error(image, | ||
| 51 | + "png_image_finish_read: " | ||
| 52 | + "16-bit PNG must use 16-bit output format"); | ||
| 53 | + if (ihdr_bit_depth < 16 && requested_linear) | ||
| 54 | + return png_image_error(image, | ||
| 55 | + "png_image_finish_read: " | ||
| 56 | + "8-bit PNG must not use 16-bit output format"); | ||
| 57 | + | ||
| 58 | memset(&display, 0, (sizeof display)); | ||
| 59 | display.image = image; | ||
| 60 | display.buffer = buffer; | ||
diff --git a/meta/recipes-multimedia/libpng/files/CVE-2025-65018-02.patch b/meta/recipes-multimedia/libpng/files/CVE-2025-65018-02.patch new file mode 100644 index 0000000000..891cd20c3f --- /dev/null +++ b/meta/recipes-multimedia/libpng/files/CVE-2025-65018-02.patch | |||
| @@ -0,0 +1,163 @@ | |||
| 1 | From 218612ddd6b17944e21eda56caf8b4bf7779d1ea Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Cosmin Truta <ctruta@gmail.com> | ||
| 3 | Date: Wed, 19 Nov 2025 21:45:13 +0200 | ||
| 4 | Subject: [PATCH] Rearchitect the fix to the buffer overflow in | ||
| 5 | `png_image_finish_read` | ||
| 6 | |||
| 7 | Undo the fix from commit 16b5e3823918840aae65c0a6da57c78a5a496a4d. | ||
| 8 | That fix turned out to be unnecessarily limiting. It rejected all | ||
| 9 | 16-to-8 bit transformations, although the vulnerability only affects | ||
| 10 | interlaced PNGs where `png_combine_row` writes using IHDR bit-depth | ||
| 11 | before the transformation completes. | ||
| 12 | |||
| 13 | The proper solution is to add an intermediate `local_row` buffer, | ||
| 14 | specifically for the slow but necessary step of 16-to-8 bit conversion | ||
| 15 | of interlaced images. (The processing of non-interlaced images remains | ||
| 16 | intact, using the fast path.) We added the flag `do_local_scale` and | ||
| 17 | the function `png_image_read_direct_scaled`, following the pattern that | ||
| 18 | involves `do_local_compose`. | ||
| 19 | |||
| 20 | In conclusion: | ||
| 21 | - The 16-to-8 bit transformations of interlaced images are now safe, | ||
| 22 | as they use an intermediate buffer. | ||
| 23 | - The 16-to-8 bit transformations of non-interlaced images remain safe, | ||
| 24 | as the fast path remains unchanged. | ||
| 25 | - All our regression tests are now passing. | ||
| 26 | |||
| 27 | CVE: CVE-2025-65018 | ||
| 28 | Upstream-Status: Backport [https://github.com/pnggroup/libpng/commit/218612ddd6b17944e21eda56caf8b4bf7779d1ea] | ||
| 29 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
| 30 | --- | ||
| 31 | pngread.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++--------- | ||
| 32 | 1 file changed, 75 insertions(+), 14 deletions(-) | ||
| 33 | |||
| 34 | diff --git a/pngread.c b/pngread.c | ||
| 35 | index 92571ec33..79917daaa 100644 | ||
| 36 | --- a/pngread.c | ||
| 37 | +++ b/pngread.c | ||
| 38 | @@ -3262,6 +3262,54 @@ png_image_read_colormapped(png_voidp argument) | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | +/* Row reading for interlaced 16-to-8 bit depth conversion with local buffer. */ | ||
| 43 | +static int | ||
| 44 | +png_image_read_direct_scaled(png_voidp argument) | ||
| 45 | +{ | ||
| 46 | + png_image_read_control *display = png_voidcast(png_image_read_control*, | ||
| 47 | + argument); | ||
| 48 | + png_imagep image = display->image; | ||
| 49 | + png_structrp png_ptr = image->opaque->png_ptr; | ||
| 50 | + png_bytep local_row = png_voidcast(png_bytep, display->local_row); | ||
| 51 | + png_bytep first_row = png_voidcast(png_bytep, display->first_row); | ||
| 52 | + ptrdiff_t row_bytes = display->row_bytes; | ||
| 53 | + int passes; | ||
| 54 | + | ||
| 55 | + /* Handle interlacing. */ | ||
| 56 | + switch (png_ptr->interlaced) | ||
| 57 | + { | ||
| 58 | + case PNG_INTERLACE_NONE: | ||
| 59 | + passes = 1; | ||
| 60 | + break; | ||
| 61 | + | ||
| 62 | + case PNG_INTERLACE_ADAM7: | ||
| 63 | + passes = PNG_INTERLACE_ADAM7_PASSES; | ||
| 64 | + break; | ||
| 65 | + | ||
| 66 | + default: | ||
| 67 | + png_error(png_ptr, "unknown interlace type"); | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + /* Read each pass using local_row as intermediate buffer. */ | ||
| 71 | + while (--passes >= 0) | ||
| 72 | + { | ||
| 73 | + png_uint_32 y = image->height; | ||
| 74 | + png_bytep output_row = first_row; | ||
| 75 | + | ||
| 76 | + for (; y > 0; --y) | ||
| 77 | + { | ||
| 78 | + /* Read into local_row (gets transformed 8-bit data). */ | ||
| 79 | + png_read_row(png_ptr, local_row, NULL); | ||
| 80 | + | ||
| 81 | + /* Copy from local_row to user buffer. */ | ||
| 82 | + memcpy(output_row, local_row, (size_t)row_bytes); | ||
| 83 | + output_row += row_bytes; | ||
| 84 | + } | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + return 1; | ||
| 88 | +} | ||
| 89 | + | ||
| 90 | /* Just the row reading part of png_image_read. */ | ||
| 91 | static int | ||
| 92 | png_image_read_composite(png_voidp argument) | ||
| 93 | @@ -3680,6 +3728,7 @@ png_image_read_direct(png_voidp argument) | ||
| 94 | int linear = (format & PNG_FORMAT_FLAG_LINEAR) != 0; | ||
| 95 | int do_local_compose = 0; | ||
| 96 | int do_local_background = 0; /* to avoid double gamma correction bug */ | ||
| 97 | + int do_local_scale = 0; /* for interlaced 16-to-8 bit conversion */ | ||
| 98 | int passes = 0; | ||
| 99 | |||
| 100 | /* Add transforms to ensure the correct output format is produced then check | ||
| 101 | @@ -3806,8 +3855,16 @@ png_image_read_direct(png_voidp argument) | ||
| 102 | png_set_expand_16(png_ptr); | ||
| 103 | |||
| 104 | else /* 8-bit output */ | ||
| 105 | + { | ||
| 106 | png_set_scale_16(png_ptr); | ||
| 107 | |||
| 108 | + /* For interlaced images, use local_row buffer to avoid overflow | ||
| 109 | + * in png_combine_row() which writes using IHDR bit-depth. | ||
| 110 | + */ | ||
| 111 | + if (png_ptr->interlaced != 0) | ||
| 112 | + do_local_scale = 1; | ||
| 113 | + } | ||
| 114 | + | ||
| 115 | change &= ~PNG_FORMAT_FLAG_LINEAR; | ||
| 116 | } | ||
| 117 | |||
| 118 | @@ -4083,6 +4140,24 @@ png_image_read_direct(png_voidp argument) | ||
| 119 | return result; | ||
| 120 | } | ||
| 121 | |||
| 122 | + else if (do_local_scale != 0) | ||
| 123 | + { | ||
| 124 | + /* For interlaced 16-to-8 conversion, use an intermediate row buffer | ||
| 125 | + * to avoid buffer overflows in png_combine_row. The local_row is sized | ||
| 126 | + * for the transformed (8-bit) output, preventing the overflow that would | ||
| 127 | + * occur if png_combine_row wrote 16-bit data directly to the user buffer. | ||
| 128 | + */ | ||
| 129 | + int result; | ||
| 130 | + png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); | ||
| 131 | + | ||
| 132 | + display->local_row = row; | ||
| 133 | + result = png_safe_execute(image, png_image_read_direct_scaled, display); | ||
| 134 | + display->local_row = NULL; | ||
| 135 | + png_free(png_ptr, row); | ||
| 136 | + | ||
| 137 | + return result; | ||
| 138 | + } | ||
| 139 | + | ||
| 140 | else | ||
| 141 | { | ||
| 142 | png_alloc_size_t row_bytes = (png_alloc_size_t)display->row_bytes; | ||
| 143 | @@ -4166,20 +4241,6 @@ png_image_finish_read(png_imagep image, png_const_colorp background, | ||
| 144 | int result; | ||
| 145 | png_image_read_control display; | ||
| 146 | |||
| 147 | - /* Reject bit depth mismatches to avoid buffer overflows. */ | ||
| 148 | - png_uint_32 ihdr_bit_depth = | ||
| 149 | - image->opaque->png_ptr->bit_depth; | ||
| 150 | - int requested_linear = | ||
| 151 | - (image->format & PNG_FORMAT_FLAG_LINEAR) != 0; | ||
| 152 | - if (ihdr_bit_depth == 16 && !requested_linear) | ||
| 153 | - return png_image_error(image, | ||
| 154 | - "png_image_finish_read: " | ||
| 155 | - "16-bit PNG must use 16-bit output format"); | ||
| 156 | - if (ihdr_bit_depth < 16 && requested_linear) | ||
| 157 | - return png_image_error(image, | ||
| 158 | - "png_image_finish_read: " | ||
| 159 | - "8-bit PNG must not use 16-bit output format"); | ||
| 160 | - | ||
| 161 | memset(&display, 0, (sizeof display)); | ||
| 162 | display.image = image; | ||
| 163 | display.buffer = buffer; | ||
diff --git a/meta/recipes-multimedia/libpng/libpng_1.6.42.bb b/meta/recipes-multimedia/libpng/libpng_1.6.42.bb index 6f5b69b754..2d5216cb65 100644 --- a/meta/recipes-multimedia/libpng/libpng_1.6.42.bb +++ b/meta/recipes-multimedia/libpng/libpng_1.6.42.bb | |||
| @@ -17,6 +17,8 @@ SRC_URI = "${SOURCEFORGE_MIRROR}/project/${BPN}/${BPN}${LIBV}/${PV}/${BP}.tar.xz | |||
| 17 | file://CVE-2025-64505-03.patch \ | 17 | file://CVE-2025-64505-03.patch \ |
| 18 | file://CVE-2025-64506.patch \ | 18 | file://CVE-2025-64506.patch \ |
| 19 | file://CVE-2025-64720.patch \ | 19 | file://CVE-2025-64720.patch \ |
| 20 | file://CVE-2025-65018-01.patch \ | ||
| 21 | file://CVE-2025-65018-02.patch \ | ||
| 20 | " | 22 | " |
| 21 | 23 | ||
| 22 | SRC_URI[sha256sum] = "c919dbc11f4c03b05aba3f8884d8eb7adfe3572ad228af972bb60057bdb48450" | 24 | SRC_URI[sha256sum] = "c919dbc11f4c03b05aba3f8884d8eb7adfe3572ad228af972bb60057bdb48450" |
