summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavi Arnaut <Davi.Arnaut@Sun.COM>2010-04-29 10:28:16 -0300
committerDavi Arnaut <Davi.Arnaut@Sun.COM>2010-04-29 10:28:16 -0300
commit14ccbeb4e40042e3fe624707d5b2e6c047149a2f (patch)
tree1f358d02b093ce9fceb5491c03a5972a53a8e8da
parent933e5ca5f0628c081484c5bc976c37db0cfbc94a (diff)
downloadmariadb-git-14ccbeb4e40042e3fe624707d5b2e6c047149a2f.tar.gz
Bug#50974: Server keeps receiving big (> max_allowed_packet) packets indefinitely.
The server could be tricked to read packets indefinitely if it received a packet larger than the maximum size of one packet. This problem is aggravated by the fact that it can be triggered before authentication. The solution is to no skip big packets for non-authenticated sessions. If a big packet is sent before a session is authen- ticated, a error is returned and the connection is closed.
-rw-r--r--include/mysql_com.h10
-rw-r--r--sql/net_serv.cc4
-rw-r--r--sql/sql_parse.cc7
3 files changed, 21 insertions, 0 deletions
diff --git a/include/mysql_com.h b/include/mysql_com.h
index 94b34c1c3f0..2eeec270cd0 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -219,6 +219,16 @@ typedef struct st_net {
my_bool report_error; /* We should report error (we have unreported error) */
my_bool return_errno;
+#if defined(MYSQL_SERVER) && !defined(EMBEDDED_LIBRARY)
+ /*
+ Controls whether a big packet should be skipped.
+
+ Initially set to FALSE by default. Unauthenticated sessions must have
+ this set to FALSE so that the server can't be tricked to read packets
+ indefinitely.
+ */
+ my_bool skip_big_packet;
+#endif
} NET;
#define packet_error (~(unsigned long) 0)
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index fdabad6f569..1d1871e27a8 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -141,6 +141,9 @@ my_bool my_net_init(NET *net, Vio* vio)
net->query_cache_query= 0;
#endif
net->report_error= 0;
+#if defined(MYSQL_SERVER) && !defined(EMBEDDED_LIBRARY)
+ net->skip_big_packet= FALSE;
+#endif
if (vio != 0) /* If real connection */
{
@@ -947,6 +950,7 @@ my_real_read(NET *net, ulong *complen)
{
#if defined(MYSQL_SERVER) && !defined(NO_ALARM)
if (!net->compress &&
+ net->skip_big_packet &&
!my_net_skip_rest(net, (uint32) len, &alarmed, &alarm_buff))
net->error= 3; /* Successfully skiped packet */
#endif
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index f1fb3d646b5..2b43d95dd7c 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -493,6 +493,13 @@ int check_user(THD *thd, enum enum_server_command command,
}
send_ok(thd);
thd->password= test(passwd_len); // remember for error messages
+ /*
+ Allow the network layer to skip big packets. Although a malicious
+ authenticated session might use this to trick the server to read
+ big packets indefinitely, this is a previously established behavior
+ that needs to be preserved as to not break backwards compatibility.
+ */
+ thd->net.skip_big_packet= TRUE;
/* Ready to handle queries */
DBUG_RETURN(0);
}