From b5aa0f437fc595d508b9eb5d36185fd8cbaa62eb Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 3 Dec 2016 20:34:50 +0100 Subject: [PATCH] MDEV-11319 mysqlbinlog crashes or fails with out of memory while reading some encrypted binlogs support encrypted binlogs. Not decryption, but at least recognizing that event are encrypted and prining them as such --- client/mysqlbinlog.cc | 12 ++++++++++- .../binlog_encryption/mysqlbinlog.result | 6 ++++++ .../suite/binlog_encryption/mysqlbinlog.test | 21 +++++++++++++++++++ sql/log_event.cc | 13 ++++++++++-- sql/log_event.h | 7 +++++-- 5 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 mysql-test/suite/binlog_encryption/mysqlbinlog.result create mode 100644 mysql-test/suite/binlog_encryption/mysqlbinlog.test diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index da41268ee19..e27a4a8e4e3 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -1257,6 +1257,9 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, goto err; break; } + case START_ENCRYPTION_EVENT: + glob_description_event->start_decryption((Start_encryption_log_event*)ev); + /* fall through */ default: print_skip_replication_statement(print_event_info, ev); ev->print(result_file, print_event_info); @@ -2837,9 +2840,16 @@ void *sql_alloc(size_t size) return alloc_root(&s_mem_root, size); } +uint dummy1() { return 1; } struct encryption_service_st encryption_handler= { - 0, 0, 0, 0, 0, 0, 0 + (uint(*)(uint))dummy1, + (uint(*)(uint, uint, uchar*, uint*))dummy1, + (uint(*)(uint, uint))dummy1, + (int (*)(void*, const uchar*, uint, const uchar*, uint, int, uint, uint))dummy1, + (int (*)(void*, const uchar*, uint, uchar*, uint*))dummy1, + (int (*)(void*, uchar*, uint*))dummy1, + (uint (*)(uint, uint, uint))dummy1 }; /* diff --git a/mysql-test/suite/binlog_encryption/mysqlbinlog.result b/mysql-test/suite/binlog_encryption/mysqlbinlog.result new file mode 100644 index 00000000000..71758f7d6e7 --- /dev/null +++ b/mysql-test/suite/binlog_encryption/mysqlbinlog.result @@ -0,0 +1,6 @@ +RESET MASTER; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); +REPLACE INTO t1 VALUES (4); +DROP TABLE t1; +FLUSH LOGS; diff --git a/mysql-test/suite/binlog_encryption/mysqlbinlog.test b/mysql-test/suite/binlog_encryption/mysqlbinlog.test new file mode 100644 index 00000000000..b80388aaa45 --- /dev/null +++ b/mysql-test/suite/binlog_encryption/mysqlbinlog.test @@ -0,0 +1,21 @@ +source include/have_log_bin.inc; +source include/have_debug.inc; + +let datadir=`select @@datadir`; +RESET MASTER; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); +REPLACE INTO t1 VALUES (4); +DROP TABLE t1; +FLUSH LOGS; + +let filename= master-bin.000001; +let local=$datadir/$filename; +let remote=--read-from-remote-server --protocol=tcp --host=127.0.0.1 --port=$MASTER_MYPORT -uroot $filename; +let outfile=$MYSQLTEST_VARDIR/tmp/binlog_enc.sql; +--error 1 +exec $MYSQL_BINLOG $local > $outfile; +exec $MYSQL_BINLOG $local --force-read >> $outfile; +exec $MYSQL_BINLOG $remote >> $outfile; +remove_file $outfile; + diff --git a/sql/log_event.cc b/sql/log_event.cc index de6528638f0..ced262657fb 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1514,6 +1514,10 @@ err: if (error) { DBUG_ASSERT(!res); +#ifdef MYSQL_CLIENT + if (force_opt) + DBUG_RETURN(new Unknown_log_event()); +#endif if (event.length() >= OLD_HEADER_LEN) sql_print_error("Error in Log_event::read_log_event(): '%s'," " data_len: %lu, event_type: %d", error, @@ -8182,8 +8186,13 @@ void Unknown_log_event::print(FILE* file_arg, PRINT_EVENT_INFO* print_event_info if (print_event_info->short_form) return; - print_header(&cache, print_event_info, FALSE); - my_b_printf(&cache, "\n# %s", "Unknown event\n"); + if (what != ENCRYPTED) + { + print_header(&cache, print_event_info, FALSE); + my_b_printf(&cache, "\n# Unknown event\n"); + } + else + my_b_printf(&cache, "# Encrypted event\n"); } #endif diff --git a/sql/log_event.h b/sql/log_event.h index bc850c22a14..90900f63533 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -1149,7 +1149,7 @@ public: return thd ? thd->db : 0; } #else - Log_event() : temp_buf(0), flags(0) {} + Log_event() : temp_buf(0), when(0), flags(0) {} ha_checksum crc; /* print*() functions are used by mysqlbinlog */ virtual void print(FILE* file, PRINT_EVENT_INFO* print_event_info) = 0; @@ -3677,6 +3677,7 @@ private: class Unknown_log_event: public Log_event { public: + enum { UNKNOWN, ENCRYPTED } what; /* Even if this is an unknown event, we still pass description_event to Log_event's ctor, this way we can extract maximum information from the @@ -3684,8 +3685,10 @@ public: */ Unknown_log_event(const char* buf, const Format_description_log_event *description_event): - Log_event(buf, description_event) + Log_event(buf, description_event), what(UNKNOWN) {} + /* constructor for hopelessly corrupted events */ + Unknown_log_event(): Log_event(), what(ENCRYPTED) {} ~Unknown_log_event() {} void print(FILE* file, PRINT_EVENT_INFO* print_event_info); Log_event_type get_type_code() { return UNKNOWN_EVENT;}