Commit d822ab89 authored by Alfranio Correia's avatar Alfranio Correia

BUG#38174 secure-file-priv breaks LOAD DATA INFILE replication in statement mode

                  
If secure-file-priv was set on slave, it became unable to execute
LOAD DATA INFILE statements sent from master using mixed or
statement-based replication.
                  
This patch fixes the issue by ignoring this security restriction
and checking if the files are created and read by the slave in the
--slave-load-tmpdir while executing the SQL Thread.
parent 9b36597a
stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
create table t1(a int not null auto_increment, b int, primary key(a));
load data infile '../../std_data/rpl_loaddata.dat' into table t1;
Comparing tables master:test.t1 and slave:test.t1
drop table t1;
##########################################################################
# This test verifies if a slave is able to process a "LOAD DATA INFILE"
# event while the "--secure-file-priv" option is set.
#
# The test is divided in two steps:
# 1 - Creates a table and populates it through "LOAD DATA INFILE".
# 2 - Compares the master and slave.
##########################################################################
source include/master-slave.inc;
##########################################################################
# Loading data
##########################################################################
connection master;
create table t1(a int not null auto_increment, b int, primary key(a));
load data infile '../../std_data/rpl_loaddata.dat' into table t1;
##########################################################################
# Checking Consistency
##########################################################################
sync_slave_with_master;
let $diff_table_1=master:test.t1;
let $diff_table_2=slave:test.t1;
source include/diff_tables.inc;
##########################################################################
# Clean up
##########################################################################
connection master;
drop table t1;
sync_slave_with_master;
...@@ -354,7 +354,7 @@ static char *slave_load_file_stem(char *buf, uint file_id, ...@@ -354,7 +354,7 @@ static char *slave_load_file_stem(char *buf, uint file_id,
int event_server_id, const char *ext) int event_server_id, const char *ext)
{ {
char *res; char *res;
fn_format(buf,"SQL_LOAD-",slave_load_tmpdir, "", MY_UNPACK_FILENAME); fn_format(buf,PREFIX_SQL_LOAD,slave_load_tmpdir, "", MY_UNPACK_FILENAME);
to_unix_path(buf); to_unix_path(buf);
buf = strend(buf); buf = strend(buf);
...@@ -393,7 +393,7 @@ static void cleanup_load_tmpdir() ...@@ -393,7 +393,7 @@ static void cleanup_load_tmpdir()
we cannot meet Start_log event in the middle of events from one we cannot meet Start_log event in the middle of events from one
LOAD DATA. LOAD DATA.
*/ */
p= strmake(prefbuf, STRING_WITH_LEN("SQL_LOAD-")); p= strmake(prefbuf, STRING_WITH_LEN(PREFIX_SQL_LOAD));
p= int10_to_str(::server_id, p, 10); p= int10_to_str(::server_id, p, 10);
*(p++)= '-'; *(p++)= '-';
*p= 0; *p= 0;
......
...@@ -47,6 +47,8 @@ ...@@ -47,6 +47,8 @@
#include "rpl_reporting.h" #include "rpl_reporting.h"
#endif #endif
#define PREFIX_SQL_LOAD "SQL_LOAD-"
/** /**
Either assert or return an error. Either assert or return an error.
......
...@@ -104,6 +104,12 @@ int init_relay_log_info(Relay_log_info* rli, ...@@ -104,6 +104,12 @@ int init_relay_log_info(Relay_log_info* rli,
rli->tables_to_lock= 0; rli->tables_to_lock= 0;
rli->tables_to_lock_count= 0; rli->tables_to_lock_count= 0;
fn_format(rli->slave_patternload_file, PREFIX_SQL_LOAD, slave_load_tmpdir, "",
MY_PACK_FILENAME | MY_UNPACK_FILENAME |
MY_RETURN_REAL_PATH);
to_unix_path(rli->slave_patternload_file);
rli->slave_patternload_file_size= strlen(rli->slave_patternload_file);
/* /*
The relay log will now be opened, as a SEQ_READ_APPEND IO_CACHE. The relay log will now be opened, as a SEQ_READ_APPEND IO_CACHE.
Note that the I/O thread flushes it to disk after writing every Note that the I/O thread flushes it to disk after writing every
......
...@@ -260,6 +260,13 @@ public: ...@@ -260,6 +260,13 @@ public:
char ign_master_log_name_end[FN_REFLEN]; char ign_master_log_name_end[FN_REFLEN];
ulonglong ign_master_log_pos_end; ulonglong ign_master_log_pos_end;
/*
Indentifies where the SQL Thread should create temporary files for the
LOAD DATA INFILE. This is used for security reasons.
*/
char slave_patternload_file[FN_REFLEN];
size_t slave_patternload_file_size;
Relay_log_info(); Relay_log_info();
~Relay_log_info(); ~Relay_log_info();
......
...@@ -15,10 +15,10 @@ ...@@ -15,10 +15,10 @@
/* Copy data from a textfile to table */ /* Copy data from a textfile to table */
#include "mysql_priv.h" #include "mysql_priv.h"
#include <my_dir.h> #include <my_dir.h>
#include <m_ctype.h> #include <m_ctype.h>
#include "rpl_mi.h"
#include "sql_repl.h" #include "sql_repl.h"
#include "sp_head.h" #include "sp_head.h"
#include "sql_trigger.h" #include "sql_trigger.h"
...@@ -310,8 +310,31 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, ...@@ -310,8 +310,31 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
is_fifo = 1; is_fifo = 1;
#endif #endif
if (opt_secure_file_priv && if (thd->slave_thread)
strncmp(opt_secure_file_priv, name, strlen(opt_secure_file_priv))) {
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
if (strncmp(active_mi->rli.slave_patternload_file, name,
active_mi->rli.slave_patternload_file_size))
{
/*
LOAD DATA INFILE in the slave SQL Thread can only read from
--slave-load-tmpdir". This should never happen. Please, report a bug.
*/
sql_print_error("LOAD DATA INFILE in the slave SQL Thread can only read from --slave-load-tmpdir. " \
"Please, report a bug.");
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--slave-load-tmpdir");
DBUG_RETURN(TRUE);
}
#else
/*
This is impossible and should never happen.
*/
DBUG_ASSERT(FALSE);
#endif
}
else if (opt_secure_file_priv &&
strncmp(opt_secure_file_priv, name, strlen(opt_secure_file_priv)))
{ {
/* Read only allowed from within dir specified by secure_file_priv */ /* Read only allowed from within dir specified by secure_file_priv */
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv"); my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment