main/mariadb-connector-c: fix CVE-2020-13249

See: #11590
This commit is contained in:
Leo 2020-12-10 23:42:12 -03:00
parent 3ac49c86ba
commit eeb63a5f99
2 changed files with 163 additions and 4 deletions

View File

@ -1,7 +1,7 @@
# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
pkgname=mariadb-connector-c
pkgver=3.0.10
pkgrel=0
pkgrel=1
pkgdesc="The MariaDB Native Client library (C driver)"
url="https://mariadb.org/"
arch="all"
@ -10,12 +10,17 @@ depends_dev="openssl-dev zlib-dev"
makedepends="$depends_dev cmake"
replaces="mariadb-client-libs"
subpackages="$pkgname-dev"
source="https://downloads.mariadb.org/interstitial/connector-c-$pkgver/mariadb-connector-c-$pkgver-src.tar.gz
source="https://downloads.mariadb.com/Connectors/c/connector-c-$pkgver/mariadb-connector-c-$pkgver-src.tar.gz
cmake.patch
fix-ucontext-header.patch
CVE-2020-13249.patch
"
builddir="$srcdir/mariadb-connector-c-$pkgver-src"
# secfixes:
# 3.0.10-r1:
# - CVE-2020-13249
build() {
cd "$builddir"
if [ "$CBUILD" != "$CHOST" ]; then
@ -57,7 +62,7 @@ dev() {
replaces="mariadb-dev"
mv "$pkgdir"/usr/bin "$subpkgdir"/usr/
}
sha512sums="1358d8f87e4693ef05d17915a399054ef40a1c9d58675b2704673fd40af843b366293c5b7d1e60c9335f68018c22d8aa86e41d90acebf1d4364229911dc8b6dc mariadb-connector-c-3.0.10-src.tar.gz
027a9d383ce27a527b77ac06b9505709cad8fe0173455863590f502996966300fedea87687630113d74e5b9be5349217b18206c2dbb89f7064129cb5417e44cf cmake.patch
757a2d3531ee271cf5473671bf4d0ac07dc8eb94ab4b6ede848ba7a55415a77f90e7275103be91c73e343e94cdbf2cd652eb6cef6ed48917991733d60d3b8777 fix-ucontext-header.patch"
757a2d3531ee271cf5473671bf4d0ac07dc8eb94ab4b6ede848ba7a55415a77f90e7275103be91c73e343e94cdbf2cd652eb6cef6ed48917991733d60d3b8777 fix-ucontext-header.patch
4370a517bc082e5aca8ebc0abf1ace7742af6cffc7f0c12b70705b31885a573192bbac473a9d0322582e64a75698db86bd36db23558dd1c1e1eaf693632a559f CVE-2020-13249.patch"

View File

@ -0,0 +1,154 @@
diff --git a/libmariadb/mariadb_lib.c b/libmariadb/mariadb_lib.c
index 4c1108b..1f04c35 100644
--- a/libmariadb/mariadb_lib.c
+++ b/libmariadb/mariadb_lib.c
@@ -76,6 +76,8 @@
#define ASYNC_CONTEXT_DEFAULT_STACK_SIZE (4096*15)
#define MA_RPL_VERSION_HACK "5.5.5-"
+#define CHARSET_NAME_LEN 64
+
#undef max_allowed_packet
#undef net_buffer_length
extern ulong max_allowed_packet; /* net.c */
@@ -2029,6 +2031,7 @@ mysql_send_query(MYSQL* mysql, const char* query, unsigned long length)
int ma_read_ok_packet(MYSQL *mysql, uchar *pos, ulong length)
{
+ uchar *end= mysql->net.read_pos+length;
size_t item_len;
mysql->affected_rows= net_field_length_ll(&pos);
mysql->insert_id= net_field_length_ll(&pos);
@@ -2036,10 +2039,14 @@ int ma_read_ok_packet(MYSQL *mysql, uchar *pos, ulong length)
pos+=2;
mysql->warning_count=uint2korr(pos);
pos+=2;
- if (pos < mysql->net.read_pos+length)
+ if (pos > end)
+ goto corrupted;
+ if (pos < end)
{
if ((item_len= net_field_length(&pos)))
mysql->info=(char*) pos;
+ if (pos + item_len > end)
+ goto corrupted;
/* check if server supports session tracking */
if (mysql->server_capabilities & CLIENT_SESSION_TRACKING)
@@ -2050,23 +2057,26 @@ int ma_read_ok_packet(MYSQL *mysql, uchar *pos, ulong length)
if (mysql->server_status & SERVER_SESSION_STATE_CHANGED)
{
int i;
- if (pos < mysql->net.read_pos + length)
+ if (pos < end)
{
LIST *session_item;
MYSQL_LEX_STRING *str= NULL;
enum enum_session_state_type si_type;
uchar *old_pos= pos;
- size_t item_len= net_field_length(&pos); /* length for all items */
+
+ item_len= net_field_length(&pos); /* length for all items */
+ if (pos + item_len > end)
+ goto corrupted;
+ end= pos + item_len;
/* length was already set, so make sure that info will be zero terminated */
if (mysql->info)
*old_pos= 0;
- while (item_len > 0)
+ while (pos < end)
{
size_t plen;
char *data;
- old_pos= pos;
si_type= (enum enum_session_state_type)net_field_length(&pos);
switch(si_type) {
case SESSION_TRACK_SCHEMA:
@@ -2076,15 +2086,14 @@ int ma_read_ok_packet(MYSQL *mysql, uchar *pos, ulong length)
if (si_type != SESSION_TRACK_STATE_CHANGE)
net_field_length(&pos); /* ignore total length, item length will follow next */
plen= net_field_length(&pos);
+ if (pos + plen > end)
+ goto corrupted;
if (!ma_multi_malloc(0,
&session_item, sizeof(LIST),
&str, sizeof(MYSQL_LEX_STRING),
&data, plen,
NULL))
- {
- SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
- return -1;
- }
+ goto oom;
str->length= plen;
str->str= data;
memcpy(str->str, (char *)pos, plen);
@@ -2107,29 +2116,28 @@ int ma_read_ok_packet(MYSQL *mysql, uchar *pos, ulong length)
if (!strncmp(str->str, "character_set_client", str->length))
set_charset= 1;
plen= net_field_length(&pos);
+ if (pos + plen > end)
+ goto corrupted;
if (!ma_multi_malloc(0,
&session_item, sizeof(LIST),
&str, sizeof(MYSQL_LEX_STRING),
&data, plen,
NULL))
- {
- SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
- return -1;
- }
+ goto oom;
str->length= plen;
str->str= data;
memcpy(str->str, (char *)pos, plen);
pos+= plen;
session_item->data= str;
mysql->extension->session_state[si_type].list= list_add(mysql->extension->session_state[si_type].list, session_item);
- if (set_charset &&
+ if (set_charset && str->length < CHARSET_NAME_LEN &&
strncmp(mysql->charset->csname, str->str, str->length) != 0)
{
- char cs_name[64];
- MARIADB_CHARSET_INFO *cs_info;
+ char cs_name[CHARSET_NAME_LEN];
+ const MARIADB_CHARSET_INFO *cs_info;
memcpy(cs_name, str->str, str->length);
cs_name[str->length]= 0;
- if ((cs_info = (MARIADB_CHARSET_INFO *)mysql_find_charset_name(cs_name)))
+ if ((cs_info = mysql_find_charset_name(cs_name)))
mysql->charset= cs_info;
}
}
@@ -2137,10 +2145,11 @@ int ma_read_ok_packet(MYSQL *mysql, uchar *pos, ulong length)
default:
/* not supported yet */
plen= net_field_length(&pos);
+ if (pos + plen > end)
+ goto corrupted;
pos+= plen;
break;
}
- item_len-= (pos - old_pos);
}
}
for (i= SESSION_TRACK_BEGIN; i <= SESSION_TRACK_END; i++)
@@ -2155,6 +2164,16 @@ int ma_read_ok_packet(MYSQL *mysql, uchar *pos, ulong length)
else if (mysql->server_capabilities & CLIENT_SESSION_TRACKING)
ma_clear_session_state(mysql);
return(0);
+
+oom:
+ ma_clear_session_state(mysql);
+ SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
+ return -1;
+
+corrupted:
+ ma_clear_session_state(mysql);
+ SET_CLIENT_ERROR(mysql, CR_MALFORMED_PACKET, SQLSTATE_UNKNOWN, 0);
+ return -1;
}
int mthd_my_read_query_result(MYSQL *mysql)