summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2010-02-23 13:04:58 +0100
committerSergei Golubchik <sergii@pisem.net>2010-02-23 13:04:58 +0100
commitf04cf03f75ffca0b99562c027c1c57340d375f66 (patch)
treec519404b0a739443194821dc72431eb35b5d4988
parent2840821cc92c302c9172ef6d47c484b5bdfcc785 (diff)
downloadmariadb-git-f04cf03f75ffca0b99562c027c1c57340d375f66.tar.gz
fix for a possible DoS in the my_net_skip_rest()
-rw-r--r--include/mysql.h.pp2
-rw-r--r--include/mysql_com.h2
-rw-r--r--sql/net_serv.cc6
-rw-r--r--sql/sql_connect.cc3
4 files changed, 10 insertions, 3 deletions
diff --git a/include/mysql.h.pp b/include/mysql.h.pp
index c333cb2bec5..3fb232cea51 100644
--- a/include/mysql.h.pp
+++ b/include/mysql.h.pp
@@ -28,7 +28,7 @@ typedef struct st_net {
unsigned int *return_status;
unsigned char reading_or_writing;
char save_char;
- my_bool unused0;
+ char net_skip_rest_factor;
my_bool unused;
my_bool compress;
my_bool unused1;
diff --git a/include/mysql_com.h b/include/mysql_com.h
index 41941d01fd2..96eb8f21d3f 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -254,7 +254,7 @@ typedef struct st_net {
unsigned int *return_status;
unsigned char reading_or_writing;
char save_char;
- my_bool unused0; /* Please remove with the next incompatible ABI change. */
+ char net_skip_rest_factor;
my_bool unused; /* Please remove with the next incompatible ABI change */
my_bool compress;
my_bool unused1; /* Please remove with the next incompatible ABI change. */
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index 4e1d507de2c..58ccde760c2 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -130,6 +130,7 @@ my_bool my_net_init(NET *net, Vio* vio)
net->last_error[0]=0;
net->compress=0; net->reading_or_writing=0;
net->where_b = net->remain_in_buf=0;
+ net->net_skip_rest_factor= 0;
net->last_errno=0;
#ifdef USE_QUERY_CACHE
query_cache_init_query(net);
@@ -743,6 +744,7 @@ static my_bool net_safe_read(NET *net, uchar *buff, size_t length,
static my_bool my_net_skip_rest(NET *net, uint32 remain, thr_alarm_t *alarmed,
ALARM *alarm_buff)
{
+ longlong limit= net->max_packet_size*net->net_skip_rest_factor;
uint32 old=remain;
DBUG_ENTER("my_net_skip_rest");
DBUG_PRINT("enter",("bytes_to_skip: %u", (uint) remain));
@@ -766,11 +768,15 @@ static my_bool my_net_skip_rest(NET *net, uint32 remain, thr_alarm_t *alarmed,
DBUG_RETURN(1);
update_statistics(thd_increment_bytes_received(length));
remain -= (uint32) length;
+ limit-= length;
+ if (limit < 0)
+ DBUG_RETURN(1);
}
if (old != MAX_PACKET_LENGTH)
break;
if (net_safe_read(net, net->buff, NET_HEADER_SIZE, alarmed))
DBUG_RETURN(1);
+ limit-= NET_HEADER_SIZE;
old=remain= uint3korr(net->buff);
net->pkt_nr++;
}
diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc
index 9f1597433d2..0de2c2d210a 100644
--- a/sql/sql_connect.cc
+++ b/sql/sql_connect.cc
@@ -474,7 +474,8 @@ check_user(THD *thd, enum enum_server_command command,
}
}
my_ok(thd);
- thd->password= test(passwd_len); // remember for error messages
+ thd->net.net_skip_rest_factor= 2; // skip at most 2*max_packet_size
+ thd->password= test(passwd_len); // remember for error messages
/* Ready to handle queries */
DBUG_RETURN(0);
}