81a4940d25
Fixes the following security issues: - CVE-2016-6328: A vulnerability was found in libexif. An integer overflow when parsing the MNOTE entry data of the input file. This can cause Denial-of-Service (DoS) and Information Disclosure (disclosing some critical heap chunk metadata, even other applications' private data). - CVE-2017-7544: libexif through 0.6.21 is vulnerable to out-of-bounds heap read vulnerability in exif_data_save_data_entry function in libexif/exif-data.c caused by improper length computation of the allocated data of an ExifMnote entry which can cause denial-of-service or possibly information disclosure. - CVE-2018-20030: An error when processing the EXIF_IFD_INTEROPERABILITY and EXIF_IFD_EXIF tags within libexif version 0.6.21 can be exploited to exhaust available CPU resources. - CVE-2019-9278: In libexif, there is a possible out of bounds write due to an integer overflow. This could lead to remote escalation of privilege in the media content provider with no additional execution privileges needed. User interaction is needed for exploitation. Signed-off-by: Peter Korsgaard <peter@korsgaard.com> Signed-off-by: Yann E. MORIN <yann.morin.1998@free.fr>
91 lines
3.3 KiB
Diff
91 lines
3.3 KiB
Diff
From 75aa73267fdb1e0ebfbc00369e7312bac43d0566 Mon Sep 17 00:00:00 2001
|
|
From: Marcus Meissner <meissner@suse.de>
|
|
Date: Sat, 18 Jan 2020 09:29:42 +0100
|
|
Subject: [PATCH] fix CVE-2019-9278
|
|
|
|
avoid the use of unsafe integer overflow checking constructs (unsigned integer operations cannot overflow, so "u1 + u2 > u1" can be optimized away)
|
|
|
|
check for the actual sizes, which should also handle the overflows
|
|
document other places google patched, but do not seem relevant due to other restrictions
|
|
|
|
fixes https://github.com/libexif/libexif/issues/26
|
|
|
|
Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
|
|
---
|
|
libexif/exif-data.c | 28 ++++++++++++++++++----------
|
|
1 file changed, 18 insertions(+), 10 deletions(-)
|
|
|
|
diff --git a/libexif/exif-data.c b/libexif/exif-data.c
|
|
index a6f9c94..6332cd1 100644
|
|
--- a/libexif/exif-data.c
|
|
+++ b/libexif/exif-data.c
|
|
@@ -192,9 +192,15 @@ exif_data_load_data_entry (ExifData *data, ExifEntry *entry,
|
|
doff = offset + 8;
|
|
|
|
/* Sanity checks */
|
|
- if ((doff + s < doff) || (doff + s < s) || (doff + s > size)) {
|
|
+ if (doff >= size) {
|
|
exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
|
|
- "Tag data past end of buffer (%u > %u)", doff+s, size);
|
|
+ "Tag starts past end of buffer (%u > %u)", doff, size);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (s > size - doff) {
|
|
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
|
|
+ "Tag data goes past end of buffer (%u > %u)", doff+s, size);
|
|
return 0;
|
|
}
|
|
|
|
@@ -315,13 +321,14 @@ exif_data_load_data_thumbnail (ExifData *data, const unsigned char *d,
|
|
unsigned int ds, ExifLong o, ExifLong s)
|
|
{
|
|
/* Sanity checks */
|
|
- if ((o + s < o) || (o + s < s) || (o + s > ds) || (o > ds)) {
|
|
- exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
|
|
- "Bogus thumbnail offset (%u) or size (%u).",
|
|
- o, s);
|
|
+ if (o >= ds) {
|
|
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", "Bogus thumbnail offset (%u).", o);
|
|
+ return;
|
|
+ }
|
|
+ if (s > ds - o) {
|
|
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", "Bogus thumbnail size (%u), max would be %u.", s, ds-o);
|
|
return;
|
|
}
|
|
-
|
|
if (data->data)
|
|
exif_mem_free (data->priv->mem, data->data);
|
|
if (!(data->data = exif_data_alloc (data, s))) {
|
|
@@ -947,7 +954,7 @@ exif_data_load_data (ExifData *data, const unsigned char *d_orig,
|
|
exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
|
|
"IFD 0 at %i.", (int) offset);
|
|
|
|
- /* Sanity check the offset, being careful about overflow */
|
|
+ /* ds is restricted to 16 bit above, so offset is restricted too, and offset+8 should not overflow. */
|
|
if (offset > ds || offset + 6 + 2 > ds)
|
|
return;
|
|
|
|
@@ -956,6 +963,7 @@ exif_data_load_data (ExifData *data, const unsigned char *d_orig,
|
|
|
|
/* IFD 1 offset */
|
|
n = exif_get_short (d + 6 + offset, data->priv->order);
|
|
+ /* offset < 2<<16, n is 16 bit at most, so this op will not overflow */
|
|
if (offset + 6 + 2 + 12 * n + 4 > ds)
|
|
return;
|
|
|
|
@@ -964,8 +972,8 @@ exif_data_load_data (ExifData *data, const unsigned char *d_orig,
|
|
exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
|
|
"IFD 1 at %i.", (int) offset);
|
|
|
|
- /* Sanity check. */
|
|
- if (offset > ds || offset + 6 > ds) {
|
|
+ /* Sanity check. ds is ensured to be above 6 above, offset is 16bit */
|
|
+ if (offset > ds - 6) {
|
|
exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA,
|
|
"ExifData", "Bogus offset of IFD1.");
|
|
} else {
|
|
--
|
|
2.20.1
|
|
|