commit:     83e075e9a297e8e1b0014f96969d477e053e2595
Author:     Thomas Deutschmann <whissi <AT> gentoo <DOT> org>
AuthorDate: Wed Mar  1 20:19:35 2017 +0000
Commit:     Thomas Deutschmann <whissi <AT> gentoo <DOT> org>
CommitDate: Wed Mar  1 20:19:35 2017 +0000
URL:        https://gitweb.gentoo.org/proj/mysql-extras.git/commit/?id=83e075e9

Add patch to mysql 5.5 branch for CVE-2017-3302

 00000_index.txt                         |   6 ++
 20023_all_mysql-5.5-CVE-2017-3302.patch | 142 ++++++++++++++++++++++++++++++++
 2 files changed, 148 insertions(+)

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 <[email protected]>
+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
+

Reply via email to