MDEV-30453 Setting innodb_buffer_pool_filename to an empty string attempts to delete the data directory on shutdown

Let us make innodb_buffer_pool_filename a read-only variable
so that a malicious user cannot cause an important file to be
deleted on InnoDB shutdown. An attempt to delete a directory
will fail because it is not a regular file, but what if the
variable pointed to (say) ibdata1, ib_logfile0 or some *.ibd file?

It does not seem to make much sense for this parameter to be
configurable in the first place, but we will not change that in order
to avoid breaking compatibility.
This commit is contained in:
Marko Mäkelä 2023-03-29 16:49:10 +03:00
parent 03b4a2d6e5
commit a6780df49b
6 changed files with 6 additions and 90 deletions

View file

@ -2,13 +2,11 @@ CREATE TABLE tab5 (col1 int auto_increment primary key,
col2 VARCHAR(25), col3 varchar(25)) ENGINE=InnoDB;
CREATE INDEX idx1 ON tab5(col2(10));
CREATE INDEX idx2 ON tab5(col3(10));
SET GLOBAL innodb_buffer_pool_filename=ib_buffer_pool100;
SET GLOBAL innodb_buffer_pool_dump_pct=100;
SELECT variable_value INTO @IBPDS
FROM information_schema.global_status
WHERE variable_name = 'INNODB_BUFFER_POOL_DUMP_STATUS';
SET GLOBAL innodb_buffer_pool_dump_now=ON;
SET GLOBAL innodb_buffer_pool_filename=ib_buffer_pool1;
SET GLOBAL innodb_buffer_pool_dump_pct=1;
SELECT @@global.innodb_buffer_pool_dump_pct;
@@global.innodb_buffer_pool_dump_pct
@ -18,5 +16,4 @@ FROM information_schema.global_status
WHERE variable_name = 'INNODB_BUFFER_POOL_DUMP_STATUS';
SET GLOBAL innodb_buffer_pool_dump_now=ON;
SET GLOBAL innodb_buffer_pool_dump_pct=DEFAULT;
SET GLOBAL innodb_buffer_pool_filename=DEFAULT;
DROP TABLE tab5;

View file

@ -25,27 +25,6 @@ select @@innodb_ft_server_stopword_table;
@@innodb_ft_server_stopword_table
NULL
drop table user_stopword_1, user_stopword_2;
select @@innodb_buffer_pool_filename;
@@innodb_buffer_pool_filename
ib_buffer_pool
set @blah='hello';
set global innodb_buffer_pool_filename = @blah;
select @@innodb_buffer_pool_filename;
@@innodb_buffer_pool_filename
hello
set global innodb_buffer_pool_filename="bye";
select @@innodb_buffer_pool_filename;
@@innodb_buffer_pool_filename
bye
set global innodb_buffer_pool_filename=NULL;
ERROR 42000: Variable 'innodb_buffer_pool_filename' can't be set to the value of 'NULL'
select @@innodb_buffer_pool_filename;
@@innodb_buffer_pool_filename
bye
set global innodb_buffer_pool_filename=default;
select @@innodb_buffer_pool_filename;
@@innodb_buffer_pool_filename
ib_buffer_pool
CREATE TABLE t1 ( id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
opening_line TEXT(500), author VARCHAR(200), title VARCHAR(200), FULLTEXT idx
(opening_line)) ENGINE=InnoDB;

View file

@ -15,7 +15,6 @@ col2 VARCHAR(25), col3 varchar(25)) ENGINE=InnoDB;
CREATE INDEX idx1 ON tab5(col2(10));
CREATE INDEX idx2 ON tab5(col3(10));
SET GLOBAL innodb_buffer_pool_filename=ib_buffer_pool100;
SET GLOBAL innodb_buffer_pool_dump_pct=100;
#***********************************************************
@ -58,8 +57,7 @@ AND variable_value != @IBPDS
AND variable_value like 'Buffer pool(s) dump completed at%';
--source include/wait_condition.inc
--file_exists $MYSQLD_DATADIR/ib_buffer_pool100
SET GLOBAL innodb_buffer_pool_filename=ib_buffer_pool1;
--move_file $MYSQLD_DATADIR/ib_buffer_pool $MYSQLD_DATADIR/ib_buffer_pool100
SET GLOBAL innodb_buffer_pool_dump_pct=1;
SELECT @@global.innodb_buffer_pool_dump_pct;
@ -83,17 +81,15 @@ AND variable_value != @IBPDS
AND variable_value like 'Buffer pool(s) dump completed at%';
--source include/wait_condition.inc
--file_exists $MYSQLD_DATADIR/ib_buffer_pool1
--file_exists $MYSQLD_DATADIR/ib_buffer_pool
perl;
my $size1 = -s "$ENV{MYSQLD_DATADIR}/ib_buffer_pool1";
my $size1 = -s "$ENV{MYSQLD_DATADIR}/ib_buffer_pool";
my $size100 = -s "$ENV{MYSQLD_DATADIR}/ib_buffer_pool100";
die "$size100<=$size1\n" unless $size100 > $size1;
EOF
SET GLOBAL innodb_buffer_pool_dump_pct=DEFAULT;
SET GLOBAL innodb_buffer_pool_filename=DEFAULT;
--remove_file $MYSQLD_DATADIR/ib_buffer_pool100
--remove_file $MYSQLD_DATADIR/ib_buffer_pool1
DROP TABLE tab5;

View file

@ -25,24 +25,6 @@ select @@innodb_ft_server_stopword_table;
drop table user_stopword_1, user_stopword_2;
#Test innodb_buffer_pool_filename (global variable)
select @@innodb_buffer_pool_filename;
set @blah='hello';
set global innodb_buffer_pool_filename = @blah;
select @@innodb_buffer_pool_filename;
set global innodb_buffer_pool_filename="bye";
select @@innodb_buffer_pool_filename;
--error ER_WRONG_VALUE_FOR_VAR
set global innodb_buffer_pool_filename=NULL;
select @@innodb_buffer_pool_filename;
set global innodb_buffer_pool_filename=default;
select @@innodb_buffer_pool_filename;
#Test innodb_ft_aux_table (global variable)
CREATE TABLE t1 ( id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
opening_line TEXT(500), author VARCHAR(200), title VARCHAR(200), FULLTEXT idx

View file

@ -221,7 +221,7 @@ NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST NULL
READ_ONLY NO
READ_ONLY YES
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME INNODB_BUFFER_POOL_INSTANCES
SESSION_VALUE NULL

View file

@ -18020,44 +18020,6 @@ exit:
return;
}
/** Validate SET GLOBAL innodb_buffer_pool_filename.
On Windows, file names with colon (:) are not allowed.
@param thd connection
@param save &srv_buf_dump_filename
@param value new value to be validated
@return 0 for valid name */
static int innodb_srv_buf_dump_filename_validate(THD *thd, st_mysql_sys_var*,
void *save,
st_mysql_value *value)
{
char buff[OS_FILE_MAX_PATH];
int len= sizeof buff;
if (const char *buf_name= value->val_str(value, buff, &len))
{
#ifdef _WIN32
if (!is_filename_allowed(buf_name, len, FALSE))
{
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_WRONG_ARGUMENTS,
"InnoDB: innodb_buffer_pool_filename "
"cannot have colon (:) in the file name.");
return 1;
}
#endif /* _WIN32 */
if (buf_name == buff)
{
ut_ad(static_cast<size_t>(len) < sizeof buff);
buf_name= thd_strmake(thd, buf_name, len);
}
*static_cast<const char**>(save)= buf_name;
return 0;
}
return 1;
}
#ifdef UNIV_DEBUG
static char* srv_buffer_pool_evict;
@ -19363,9 +19325,9 @@ static MYSQL_SYSVAR_ULONG(buffer_pool_instances, srv_buf_pool_instances,
NULL, NULL, srv_buf_pool_instances_default, 0, MAX_BUFFER_POOLS, 0);
static MYSQL_SYSVAR_STR(buffer_pool_filename, srv_buf_dump_filename,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
"Filename to/from which to dump/load the InnoDB buffer pool",
innodb_srv_buf_dump_filename_validate, NULL, SRV_BUF_DUMP_FILENAME_DEFAULT);
NULL, NULL, SRV_BUF_DUMP_FILENAME_DEFAULT);
static MYSQL_SYSVAR_BOOL(buffer_pool_dump_now, innodb_buffer_pool_dump_now,
PLUGIN_VAR_RQCMDARG,