1
0
mirror of https://github.com/MariaDB/server.git synced 2026-10-23 18:49:29 +03:00

MDEV-40425 handlersocket crashes on read with huge number of fields

* fix handlersocket to unlink it's THD, this apparently was broken
  for years
* add a check for fldnum
* add a first ever handlersocket test
This commit is contained in:
Sergei Golubchik
2026-07-17 16:01:08 +02:00
parent 98437c30ae
commit 3f6f51e662
5 changed files with 46 additions and 6 deletions

View File

@@ -337,6 +337,7 @@ dbcontext::term_thread()
close_tables_if();
set_current_thd(nullptr);
{
server_threads.erase(thd);
delete thd;
thd = 0;
my_thread_end();

View File

@@ -768,6 +768,9 @@ hstcpsvr_worker::do_exec_on_index(char *cmd_begin, char *cmd_end, char *start,
args.op = string_ref(op_begin, op_end);
skip_one(start, finish);
const uint32_t fldnum = read_ui32(start, finish);
if (fldnum > 32) {
return conn.dbcb_resp_short(2, "fldnum");
}
string_ref *const flds = DENA_ALLOCA_ALLOCATE(string_ref, fldnum);
auto_alloca_free<string_ref> flds_autofree(flds);
args.kvals = flds;

View File

@@ -0,0 +1,4 @@
!include include/default_my.cnf
[mysqld.1]
loose-handlersocket-port=@OPT.port

View File

@@ -1,3 +1,4 @@
call mtr.add_suppression('handlersocket: open_files_limit is too small');
install plugin handlersocket soname 'handlersocket.so';
select plugin_name, plugin_version, plugin_status, plugin_type, plugin_library, plugin_library_version, plugin_author, plugin_description, plugin_license, plugin_maturity, plugin_auth_version from information_schema.plugins where plugin_name = 'handlersocket';
plugin_name handlersocket
@@ -11,13 +12,15 @@ plugin_description Direct access into InnoDB
plugin_license BSD
plugin_maturity Beta
plugin_auth_version 1.1
select * from information_schema.global_variables where variable_name like 'handlersocket%' and variable_name not like '%secret%' order by variable_name;
select * from information_schema.global_variables where variable_name like 'handlersocket%' order by variable_name;
VARIABLE_NAME VARIABLE_VALUE
HANDLERSOCKET_ACCEPT_BALANCE 0
HANDLERSOCKET_ADDRESS
HANDLERSOCKET_BACKLOG 32768
HANDLERSOCKET_EPOLL 1
HANDLERSOCKET_PORT
HANDLERSOCKET_PLAIN_SECRET HS_SECRET
HANDLERSOCKET_PLAIN_SECRET_WR HS_SECRET
HANDLERSOCKET_PORT HS_PORT
HANDLERSOCKET_PORT_WR
HANDLERSOCKET_RCVBUF 0
HANDLERSOCKET_READSIZE 0
@@ -30,4 +33,9 @@ HANDLERSOCKET_WRLOCK_TIMEOUT 12
select length(@@handlersocket_plain_secret), @@handlersocket_plain_secret = @@handlersocket_plain_secret_wr;
length(@@handlersocket_plain_secret) @@handlersocket_plain_secret = @@handlersocket_plain_secret_wr
16 1
create table t1 (id int primary key, name varchar(100)) engine=innodb;
auth: 0 1
open: 0 1
bad read: 2 1 fldnum
uninstall plugin handlersocket;
drop table t1;

View File

@@ -1,8 +1,32 @@
--source include/not_windows_embedded.inc
--source include/have_innodb.inc
--source include/not_asan.inc
call mtr.add_suppression('handlersocket: open_files_limit is too small');
install plugin handlersocket soname 'handlersocket.so';
--query_vertical select plugin_name, plugin_version, plugin_status, plugin_type, plugin_library, plugin_library_version, plugin_author, plugin_description, plugin_license, plugin_maturity, plugin_auth_version from information_schema.plugins where plugin_name = 'handlersocket'
select * from information_schema.global_variables where variable_name like 'handlersocket%' and variable_name not like '%secret%' order by variable_name;
select length(@@handlersocket_plain_secret), @@handlersocket_plain_secret = @@handlersocket_plain_secret_wr;
uninstall plugin handlersocket;
let HS_SECRET=`select @@handlersocket_plain_secret`;
let HS_PORT=`select @@handlersocket_port`;
--query_vertical select plugin_name, plugin_version, plugin_status, plugin_type, plugin_library, plugin_library_version, plugin_author, plugin_description, plugin_license, plugin_maturity, plugin_auth_version from information_schema.plugins where plugin_name = 'handlersocket'
--replace_result $HS_SECRET HS_SECRET $HS_PORT HS_PORT
select * from information_schema.global_variables where variable_name like 'handlersocket%' order by variable_name;
select length(@@handlersocket_plain_secret), @@handlersocket_plain_secret = @@handlersocket_plain_secret_wr;
create table t1 (id int primary key, name varchar(100)) engine=innodb;
perl;
use IO::Socket::INET;
my $sock = IO::Socket::INET->new(PeerAddr => '127.0.0.1',
PeerPort => $ENV{HS_PORT}, Proto => 'tcp') or die "connect(): $!";
# 1) auth: A <atyp=1> <secret>
# 2) open_index: P <indexid> <db> <table> <index> <columns>
print $sock "A\t1\t$ENV{HS_SECRET}\nP\t1\ttest\tt1\tPRIMARY\tid,name\n";
print $sock "0\t=\t2147483647\t1\n";
printf "auth: %sopen: %sbad read: %s", scalar(<$sock>), scalar(<$sock>), scalar(<$sock>);
EOF
uninstall plugin handlersocket;
drop table t1;