fix cve-2021-29464 cve-2021-29463 cve-2021-29473

This commit is contained in:
linker 2021-05-12 10:47:26 +08:00
parent 050bf70d50
commit 6ce4fdcb4c
6 changed files with 356 additions and 1 deletions

View File

@ -0,0 +1,26 @@
From caa4e6745a76a23bb80127cf54c0d65096ae684c Mon Sep 17 00:00:00 2001
From: Kevin Backhouse <kev@semmle.com>
Date: Tue, 30 Apr 2019 09:26:18 +0100
Subject: [PATCH] Avoid negative integer overflow when `filesize <
io_->tell()`.
This fixes #791.
---
src/webpimage.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/webpimage.cpp b/src/webpimage.cpp
index 9d7272c..6fe2ddb 100644
--- a/src/webpimage.cpp
+++ b/src/webpimage.cpp
@@ -45,6 +45,7 @@
#include "tiffimage_int.hpp"
#include "convert.hpp"
#include "enforce.hpp"
+#include "safe_op.hpp"
#include <cmath>
#include <iomanip>
--
2.23.0

View File

@ -0,0 +1,116 @@
From caa4e6745a76a23bb80127cf54c0d65096ae684c Mon Sep 17 00:00:00 2001
From: Kevin Backhouse <kev@semmle.com>
Date: Tue, 30 Apr 2019 09:26:18 +0100
Subject: [PATCH] Avoid negative integer overflow when `filesize <
io_->tell()`.
This fixes #791.
---
src/webpimage.cpp | 33 +++++++++++++++++++++------------
1 file changed, 21 insertions(+), 12 deletions(-)
diff --git a/src/webpimage.cpp b/src/webpimage.cpp
index 51a200b..9d7272c 100644
--- a/src/webpimage.cpp
+++ b/src/webpimage.cpp
@@ -67,6 +67,15 @@ namespace Exiv2 {
namespace Exiv2 {
using namespace Exiv2::Internal;
+ // This static function is a temporary fix in v0.27. In the next version,
+ // it will be added as a method of BasicIo.
+ static void readOrThrow(BasicIo& iIo, byte* buf, long rcount, ErrorCode err) {
+ const long nread = iIo.read(buf, rcount);
+ enforce(nread == rcount, err);
+ enforce(!iIo.error(), err);
+ }
+
+
WebPImage::WebPImage(BasicIo::AutoPtr io)
: Image(ImageType::webp, mdNone, io)
{
@@ -512,7 +521,7 @@ namespace Exiv2 {
DataBuf chunkId(5);
chunkId.pData_[4] = '\0' ;
- io_->readOrThrow(data, WEBP_TAG_SIZE * 3, Exiv2::kerCorruptedMetadata);
+ readOrThrow(*io_, data, WEBP_TAG_SIZE * 3, Exiv2::kerCorruptedMetadata);
const uint32_t filesize = Exiv2::getULong(data + WEBP_TAG_SIZE, littleEndian) + 8;
enforce(filesize <= io_->size(), Exiv2::kerCorruptedMetadata);
@@ -532,8 +541,8 @@ namespace Exiv2 {
chunkId.pData_[4] = '\0' ;
while ( !io_->eof() && (uint64_t) io_->tell() < filesize) {
- io_->readOrThrow(chunkId.pData_, WEBP_TAG_SIZE, Exiv2::kerCorruptedMetadata);
- io_->readOrThrow(size_buff, WEBP_TAG_SIZE, Exiv2::kerCorruptedMetadata);
+ readOrThrow(*io_, chunkId.pData_, WEBP_TAG_SIZE, Exiv2::kerCorruptedMetadata);
+ readOrThrow(*io_, size_buff, WEBP_TAG_SIZE, Exiv2::kerCorruptedMetadata);
const uint32_t size = Exiv2::getULong(size_buff, littleEndian);
enforce(io_->tell() <= filesize, Exiv2::kerCorruptedMetadata);
enforce(size <= (filesize - io_->tell()), Exiv2::kerCorruptedMetadata);
@@ -545,8 +554,8 @@ namespace Exiv2 {
has_canvas_data = true;
byte size_buf[WEBP_TAG_SIZE];
-
- io_->readOrThrow(payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata);
+
+ readOrThrow(*io_, payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata);
// Fetch width
memcpy(&size_buf, &payload.pData_[4], 3);
@@ -561,7 +570,7 @@ namespace Exiv2 {
enforce(size >= 10, Exiv2::kerCorruptedMetadata);
has_canvas_data = true;
- io_->readOrThrow(payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata);
+ readOrThrow(*io_, payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata);
byte size_buf[WEBP_TAG_SIZE];
// Fetch width""
@@ -582,7 +591,7 @@ namespace Exiv2 {
byte size_buf_w[2];
byte size_buf_h[3];
- io_->readOrThrow(payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata);
+ readOrThrow(*io_, payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata);
// Fetch width
memcpy(&size_buf_w, &payload.pData_[1], 2);
@@ -599,8 +608,8 @@ namespace Exiv2 {
has_canvas_data = true;
byte size_buf[WEBP_TAG_SIZE];
-
- io_->readOrThrow(payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata);
+
+ readOrThrow(*io_, payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata);
// Fetch width
memcpy(&size_buf, &payload.pData_[6], 3);
@@ -612,10 +621,10 @@ namespace Exiv2 {
size_buf[3] = 0;
pixelHeight_ = Exiv2::getULong(size_buf, littleEndian) + 1;
} else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_ICCP)) {
- io_->readOrThrow(payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata);
+ readOrThrow(*io_, payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata);
this->setIccProfile(payload);
} else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_EXIF)) {
- io_->readOrThrow(payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata);
+ readOrThrow(*io_, payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata);
byte size_buff[2];
byte exifLongHeader[] = { 0xFF, 0x01, 0xFF, 0xE1 };
@@ -696,7 +705,7 @@ namespace Exiv2 {
if (rawExifData) free(rawExifData);
} else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_XMP)) {
- io_->readOrThrow(payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata);
+ readOrThrow(*io_, payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata);
xmpPacket_.assign(reinterpret_cast<char*>(payload.pData_), payload.size_);
if (xmpPacket_.size() > 0 && XmpParser::decode(xmpData_, xmpPacket_)) {
#ifndef SUPPRESS_WARNINGS
--
2.23.0

View File

@ -0,0 +1,123 @@
From 783b3a6ff15ed6f82a8f8e6c8a6f3b84a9b04d4b Mon Sep 17 00:00:00 2001
From: Kevin Backhouse <kevinbackhouse@github.com>
Date: Mon, 19 Apr 2021 18:06:00 +0100
Subject: [PATCH] Improve bound checking in WebPImage::doWriteMetadata()
---
src/webpimage.cpp | 41 ++++++++++++++++++++++++++++++-----------
1 file changed, 30 insertions(+), 11 deletions(-)
diff --git a/src/webpimage.cpp b/src/webpimage.cpp
index c12e8fb..51a200b 100644
--- a/src/webpimage.cpp
+++ b/src/webpimage.cpp
@@ -144,7 +144,7 @@ namespace Exiv2 {
DataBuf chunkId(WEBP_TAG_SIZE+1);
chunkId.pData_ [WEBP_TAG_SIZE] = '\0';
- io_->read(data, WEBP_TAG_SIZE * 3);
+ readOrThrow(*io_, data, WEBP_TAG_SIZE * 3, Exiv2::kerCorruptedMetadata);
uint64_t filesize = Exiv2::getULong(data + WEBP_TAG_SIZE, littleEndian);
/* Set up header */
@@ -183,13 +183,20 @@ namespace Exiv2 {
case we have any exif or xmp data, also check
for any chunks with alpha frame/layer set */
while ( !io_->eof() && (uint64_t) io_->tell() < filesize) {
- io_->read(chunkId.pData_, WEBP_TAG_SIZE);
- io_->read(size_buff, WEBP_TAG_SIZE);
- long size = Exiv2::getULong(size_buff, littleEndian);
+ readOrThrow(*io_, chunkId.pData_, WEBP_TAG_SIZE, Exiv2::kerCorruptedMetadata);
+ readOrThrow(*io_, size_buff, WEBP_TAG_SIZE, Exiv2::kerCorruptedMetadata);
+ const uint32_t size_u32 = Exiv2::getULong(size_buff, littleEndian);
+
+ // Check that `size_u32` is safe to cast to `long`.
+ enforce(size_u32 <= static_cast<size_t>(std::numeric_limits<unsigned int>::max()),
+ Exiv2::kerCorruptedMetadata);
+ const long size = static_cast<long>(size_u32);
DataBuf payload(size);
- io_->read(payload.pData_, payload.size_);
- byte c;
- if ( payload.size_ % 2 ) io_->read(&c,1);
+ readOrThrow(*io_, payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata);
+ if ( payload.size_ % 2 ) {
+ byte c;
+ readOrThrow(*io_, &c, 1, Exiv2::kerCorruptedMetadata);
+ }
/* Chunk with information about features
used in the file. */
@@ -197,6 +204,7 @@ namespace Exiv2 {
has_vp8x = true;
}
if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8X) && !has_size) {
+ enforce(size >= 10, Exiv2::kerCorruptedMetadata);
has_size = true;
byte size_buf[WEBP_TAG_SIZE];
@@ -225,6 +233,7 @@ namespace Exiv2 {
}
#endif
if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8) && !has_size) {
+ enforce(size >= 10, Exiv2::kerCorruptedMetadata);
has_size = true;
byte size_buf[2];
@@ -242,11 +251,13 @@ namespace Exiv2 {
/* Chunk with with lossless image data. */
if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8L) && !has_alpha) {
+ enforce(size >= 5, Exiv2::kerCorruptedMetadata);
if ((payload.pData_[5] & WEBP_VP8X_ALPHA_BIT) == WEBP_VP8X_ALPHA_BIT) {
has_alpha = true;
}
}
if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8L) && !has_size) {
+ enforce(size >= 5, Exiv2::kerCorruptedMetadata);
has_size = true;
byte size_buf_w[2];
byte size_buf_h[3];
@@ -274,11 +285,13 @@ namespace Exiv2 {
/* Chunk with animation frame. */
if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_ANMF) && !has_alpha) {
+ enforce(size >= 6, Exiv2::kerCorruptedMetadata);
if ((payload.pData_[5] & 0x2) == 0x2) {
has_alpha = true;
}
}
if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_ANMF) && !has_size) {
+ enforce(size >= 12, Exiv2::kerCorruptedMetadata);
has_size = true;
byte size_buf[WEBP_TAG_SIZE];
@@ -307,16 +320,22 @@ namespace Exiv2 {
io_->seek(12, BasicIo::beg);
while ( !io_->eof() && (uint64_t) io_->tell() < filesize) {
- io_->read(chunkId.pData_, 4);
- io_->read(size_buff, 4);
+ readOrThrow(*io_, chunkId.pData_, 4, Exiv2::kerCorruptedMetadata);
+ readOrThrow(*io_, size_buff, 4, Exiv2::kerCorruptedMetadata);
+
+ const uint32_t size_u32 = Exiv2::getULong(size_buff, littleEndian);
- long size = Exiv2::getULong(size_buff, littleEndian);
+ // Check that `size_u32` is safe to cast to `long`.
+ enforce(size_u32 <= static_cast<size_t>(std::numeric_limits<unsigned int>::max()),
+ Exiv2::kerCorruptedMetadata);
+ const long size = static_cast<long>(size_u32);
DataBuf payload(size);
- io_->read(payload.pData_, size);
+ readOrThrow(*io_, payload.pData_, size, Exiv2::kerCorruptedMetadata);
if ( io_->tell() % 2 ) io_->seek(+1,BasicIo::cur); // skip pad
if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8X)) {
+ enforce(size >= 1, Exiv2::kerCorruptedMetadata);
if (has_icc){
payload.pData_[0] |= WEBP_VP8X_ICC_BIT;
} else {
--
2.23.0

View File

@ -0,0 +1,55 @@
From f9308839198aca5e68a65194f151a1de92398f54 Mon Sep 17 00:00:00 2001
From: Kevin Backhouse <kevinbackhouse@github.com>
Date: Tue, 20 Apr 2021 12:04:13 +0100
Subject: [PATCH] Better bounds checking in Jp2Image::encodeJp2Header()
---
src/jp2image.cpp | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/jp2image.cpp b/src/jp2image.cpp
index 0825d99..f9be021 100644
--- a/src/jp2image.cpp
+++ b/src/jp2image.cpp
@@ -650,6 +650,7 @@ namespace Exiv2
#ifdef DEBUG
std::cout << "Jp2Image::encodeJp2Header subbox: "<< toAscii(subBox.type) << " length = " << subBox.length << std::endl;
#endif
+ enforce(subBox.length <= length - count, Exiv2::kerCorruptedMetadata);
count += subBox.length;
newBox.type = subBox.type;
} else {
@@ -658,12 +659,13 @@ namespace Exiv2
count = length;
}
- int32_t newlen = subBox.length;
+ uint32_t newlen = subBox.length;
if ( newBox.type == kJp2BoxTypeColorHeader ) {
bWroteColor = true ;
if ( ! iccProfileDefined() ) {
const char* pad = "\x01\x00\x00\x00\x00\x00\x10\x00\x00\x05\x1cuuid";
uint32_t psize = 15;
+ enforce(newlen <= output.size_ - outlen, Exiv2::kerCorruptedMetadata);
ul2Data((byte*)&newBox.length,psize ,bigEndian);
ul2Data((byte*)&newBox.type ,newBox.type,bigEndian);
::memcpy(output.pData_+outlen ,&newBox ,sizeof(newBox));
@@ -672,6 +674,7 @@ namespace Exiv2
} else {
const char* pad = "\0x02\x00\x00";
uint32_t psize = 3;
+ enforce(newlen <= output.size_ - outlen, Exiv2::kerCorruptedMetadata);
ul2Data((byte*)&newBox.length,psize+iccProfile_.size_,bigEndian);
ul2Data((byte*)&newBox.type,newBox.type,bigEndian);
::memcpy(output.pData_+outlen ,&newBox ,sizeof(newBox) );
@@ -680,6 +683,7 @@ namespace Exiv2
newlen = psize + iccProfile_.size_;
}
} else {
+ enforce(newlen <= output.size_ - outlen, Exiv2::kerCorruptedMetadata);
::memcpy(output.pData_+outlen,boxBuf.pData_+inlen,subBox.length);
}
--
2.23.0

View File

@ -0,0 +1,24 @@
From e6a0982f7cd9282052b6e3485a458d60629ffa0b Mon Sep 17 00:00:00 2001
From: Kevin Backhouse <kevinbackhouse@github.com>
Date: Fri, 23 Apr 2021 11:44:44 +0100
Subject: [PATCH] Add bounds check in Jp2Image::doWriteMetadata().
---
src/jp2image.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/jp2image.cpp b/src/jp2image.cpp
index f9be021..40eca0d 100644
--- a/src/jp2image.cpp
+++ b/src/jp2image.cpp
@@ -888,6 +888,7 @@ namespace Exiv2
case kJp2BoxTypeUuid:
{
+ enforce(boxBuf.size_ >= 24, Exiv2::kerCorruptedMetadata);
if(memcmp(boxBuf.pData_ + 8, kJp2UuidExif, 16) == 0)
{
#ifdef DEBUG
--
2.23.0

View File

@ -1,6 +1,6 @@
Name: exiv2 Name: exiv2
Version: 0.26 Version: 0.26
Release: 25 Release: 26
Summary: Exif, IPTC and XMP metadata and the ICC Profile Summary: Exif, IPTC and XMP metadata and the ICC Profile
License: GPLv2+ License: GPLv2+
URL: http://www.exiv2.org/ URL: http://www.exiv2.org/
@ -62,6 +62,11 @@ Patch6029: CVE-2021-3482.patch
Patch6030: backport-CVE-2021-29457.patch Patch6030: backport-CVE-2021-29457.patch
Patch6031: backport-CVE-2021-29458.patch Patch6031: backport-CVE-2021-29458.patch
Patch6032: backport-CVE-2021-29470.patch Patch6032: backport-CVE-2021-29470.patch
Patch6033: backport-0001-CVE-2021-29463.patch
Patch6034: backport-0002-CVE-2021-29463.patch
Patch6035: backport-CVE-2021-29464.patch
Patch6036: backport-CVE-2021-29463.patch
Patch6037: backport-CVE-2021-29473.patch
Provides: exiv2-libs Provides: exiv2-libs
Obsoletes: exiv2-libs Obsoletes: exiv2-libs
@ -125,6 +130,12 @@ test -x %{buildroot}%{_libdir}/libexiv2.so
%{_datadir}/doc/html/ %{_datadir}/doc/html/
%changelog %changelog
* Wed May 12 2021 wangkerong <wangkerong@huawei.com> - 0.26-26
- Type:cves
- ID:CVE-2021-29464 CVE-2021-29463 CVE-2021-29473
- SUG:NA
- DESC:fix CVE-2021-29464,CVE-2021-29463,CVE-2021-29473
* Sat May 08 2021 wangkerong <wangkerong@huawei.com> - 0.26-25 * Sat May 08 2021 wangkerong <wangkerong@huawei.com> - 0.26-25
- Type:cve - Type:cve
- ID:CVE-2021-29470 - ID:CVE-2021-29470