summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Deutschmann <whissi@gentoo.org>2017-03-01 21:19:35 +0100
committerThomas Deutschmann <whissi@gentoo.org>2017-03-01 21:19:35 +0100
commit83e075e9a297e8e1b0014f96969d477e053e2595 (patch)
tree93cd27a318d58f21ca451e108671bc05cebe417e
parentFix support for minizip in Mariadb ConnectSE (diff)
downloadmysql-extras-83e075e9.tar.gz
mysql-extras-83e075e9.tar.bz2
mysql-extras-83e075e9.zip
Add patch to mysql 5.5 branch for CVE-2017-3302mysql-extras-20170301-2020Z
-rw-r--r--00000_index.txt6
-rw-r--r--20023_all_mysql-5.5-CVE-2017-3302.patch142
2 files changed, 148 insertions, 0 deletions
diff --git a/00000_index.txt b/00000_index.txt
index 8f3a4c3..3c8627f 100644
--- a/00000_index.txt
+++ b/00000_index.txt
@@ -946,3 +946,9 @@
@ver 10.01.11.00 to 10.01.11.99
@pn mariadb
@@ Fix server gssapi plugin compile with heimdal
+
+@patch 20023_all_mysql-5.5-CVE-2017-3302.patch
+@ver 5.05.45.00 to 5.05.54.99
+@pn mysql
+@@ Fix use-after-free in mysql_prune_stmt_list
+@@ Back ported from mysql 5.6; Oracle bug 17512527
diff --git a/20023_all_mysql-5.5-CVE-2017-3302.patch b/20023_all_mysql-5.5-CVE-2017-3302.patch
new file mode 100644
index 0000000..23bff1a
--- /dev/null
+++ b/20023_all_mysql-5.5-CVE-2017-3302.patch
@@ -0,0 +1,142 @@
+From 1037977895aa4a145de16719df0a2375c71bbf26 Mon Sep 17 00:00:00 2001
+From: Nisha Gopalakrishnan <nisha.gopalakrishnan@oracle.com>
+Date: Mon, 21 Jul 2014 21:21:15 +0530
+Subject: [PATCH] BUG#17512527: LIST HANDLING INCORRECT IN
+ MYSQL_PRUNE_STMT_LIST()
+
+Analysis:
+---------
+Invalid memory access maybe observed when using prepared statements if:
+a) The mysql client connection is lost after statement preparation
+ is complete and
+b) There is at least one statement which is in initialized state but
+ not prepared yet.
+
+When the client detects a closed connection, it calls end_server()
+to shutdown the connection. As part of the clean up, the
+mysql_prune_stmt_list() removes the statements which has transitioned
+beyond the initialized state and retains only the statements which
+are in a initialized state. During this processing, the initialized
+statements are moved from 'mysql->stmts' to a temporary 'pruned_list'.
+When moving the first 'INIT_DONE' element to the pruned_list,
+'element->next' is set to NULL. Hence the rest of the list is never
+traversed and the statements which have transitioned beyond the
+initialized state are never invalidated.
+
+When the mysql_stmt_close() is called for the statement which is not
+invalidated; the statements list is updated in order to remove the
+statement. This would end up accessing freed memory(freed by the
+mysql_stmt_close() for a previous statement in the list).
+
+Fix:
+---
+mysql_prune_stmt_list() called list_add() incorrectly to create a
+temporary list. The use case of list_add() is to add a single
+element to the front of the doubly linked list.
+mysql_prune_stmt_list() called list_add() by passing an entire
+list as the 'element'.
+
+mysql_prune_stmt_list() now uses list_delete() to remove the
+statement which has transitioned beyond the initialized phase.
+Thus the statement list would contain only elements where the
+the state of the statement is initialized.
+
+Note: Run the test with valgrind-mysqltest and leak-check=full
+option to see the invalid memory access.
+
+Back-ported to MySQL 5.5 branch by Balint Reczey
+
+Conflicts:
+ sql-common/client.c
+ tests/mysql_client_test.c
+---
+ sql-common/client.c | 11 +++++++----
+ tests/mysql_client_test.c | 41 +++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 48 insertions(+), 4 deletions(-)
+
+diff --git a/sql-common/client.c b/sql-common/client.c
+index cd9b6a7..be60cc1 100644
+--- a/sql-common/client.c
++++ b/sql-common/client.c
+@@ -3790,12 +3790,15 @@ static void mysql_close_free(MYSQL *mysql)
+ */
+ static void mysql_prune_stmt_list(MYSQL *mysql)
+ {
+- LIST *element= mysql->stmts;
+- LIST *pruned_list= 0;
++ LIST *pruned_list= NULL;
+
+- for (; element; element= element->next)
++ while(mysql->stmts)
+ {
+- MYSQL_STMT *stmt= (MYSQL_STMT *) element->data;
++ LIST *element= mysql->stmts;
++ MYSQL_STMT *stmt;
++
++ mysql->stmts= list_delete(element, element);
++ stmt= (MYSQL_STMT *) element->data;
+ if (stmt->state != MYSQL_STMT_INIT_DONE)
+ {
+ stmt->mysql= 0;
+diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
+index e600d82..d3f3899 100644
+--- a/tests/mysql_client_test.c
++++ b/tests/mysql_client_test.c
+@@ -18648,6 +18648,46 @@ static void test_bug13001491()
+ myquery(rc);
+ }
+
++static void test_bug17512527()
++{
++ MYSQL *conn1, *conn2;
++ MYSQL_STMT *stmt1, *stmt2;
++ const char *stmt1_txt= "SELECT NOW();";
++ const char *stmt2_txt= "SELECT 1;";
++ unsigned long thread_id;
++ char query[MAX_TEST_QUERY_LENGTH];
++ int rc;
++
++ conn1= client_connect(0, MYSQL_PROTOCOL_DEFAULT, 1);
++ conn2= client_connect(0, MYSQL_PROTOCOL_DEFAULT, 0);
++
++ stmt1 = mysql_stmt_init(conn1);
++ check_stmt(stmt1);
++ rc= mysql_stmt_prepare(stmt1, stmt1_txt, strlen(stmt1_txt));
++ check_execute(stmt1, rc);
++
++ thread_id= mysql_thread_id(conn1);
++ sprintf(query, "KILL %lu", thread_id);
++ if (thread_query(query))
++ exit(1);
++
++ /*
++ After the connection is killed, the connection is
++ re-established due to the reconnect flag.
++ */
++ stmt2 = mysql_stmt_init(conn1);
++ check_stmt(stmt2);
++
++ rc= mysql_stmt_prepare(stmt2, stmt2_txt, strlen(stmt2_txt));
++ check_execute(stmt1, rc);
++
++ mysql_stmt_close(stmt2);
++ mysql_stmt_close(stmt1);
++
++ mysql_close(conn1);
++ mysql_close(conn2);
++}
++
+
+ static struct my_tests_st my_tests[]= {
+ { "disable_query_logs", disable_query_logs },
+@@ -18911,6 +18951,7 @@ static struct my_tests_st my_tests[]= {
+ { "test_bug12337762", test_bug12337762 },
+ { "test_bug11754979", test_bug11754979 },
+ { "test_bug13001491", test_bug13001491 },
++ { "test_bug17512527", test_bug17512527},
+ { 0, 0 }
+ };
+
+--
+2.1.4
+