diff options
author | Sergei Golubchik <sergii@pisem.net> | 2010-02-23 13:04:58 +0100 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2010-02-23 13:04:58 +0100 |
commit | f04cf03f75ffca0b99562c027c1c57340d375f66 (patch) | |
tree | c519404b0a739443194821dc72431eb35b5d4988 | |
parent | 2840821cc92c302c9172ef6d47c484b5bdfcc785 (diff) | |
download | mariadb-git-f04cf03f75ffca0b99562c027c1c57340d375f66.tar.gz |
fix for a possible DoS in the my_net_skip_rest()
-rw-r--r-- | include/mysql.h.pp | 2 | ||||
-rw-r--r-- | include/mysql_com.h | 2 | ||||
-rw-r--r-- | sql/net_serv.cc | 6 | ||||
-rw-r--r-- | sql/sql_connect.cc | 3 |
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); } |