diff options
Diffstat (limited to 'extra')
-rw-r--r-- | extra/innochecksum.cc | 11 | ||||
-rw-r--r-- | extra/mariabackup/backup_copy.cc | 6 | ||||
-rw-r--r-- | extra/mariabackup/fil_cur.cc | 11 | ||||
-rw-r--r-- | extra/mariabackup/xtrabackup.cc | 170 |
4 files changed, 190 insertions, 8 deletions
diff --git a/extra/innochecksum.cc b/extra/innochecksum.cc index e4b81dff34c..5c6cf74fd8e 100644 --- a/extra/innochecksum.cc +++ b/extra/innochecksum.cc @@ -524,7 +524,16 @@ is_page_corrupted( normal method. */ if (is_encrypted && key_version != 0) { is_corrupted = !fil_space_verify_crypt_checksum(buf, - page_size, space_id, (ulint)cur_page_num); + page_size); + if (is_corrupted && log_file) { + fprintf(log_file, + "Page " ULINTPF ":%llu may be corrupted;" + " key_version=%u\n", + space_id, cur_page_num, + mach_read_from_4( + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + + buf)); + } } else { is_corrupted = true; } diff --git a/extra/mariabackup/backup_copy.cc b/extra/mariabackup/backup_copy.cc index 1e2d57626e1..4573c1977e7 100644 --- a/extra/mariabackup/backup_copy.cc +++ b/extra/mariabackup/backup_copy.cc @@ -1395,7 +1395,9 @@ static lsn_t get_current_lsn(MYSQL *connection) "SHOW ENGINE INNODB STATUS", true, false)) { if (MYSQL_ROW row = mysql_fetch_row(res)) { - if (const char *p = strstr(row[2], lsn_prefix)) { + const char *p= strstr(row[2], lsn_prefix); + DBUG_ASSERT(p); + if (p) { p += sizeof lsn_prefix - 1; lsn = lsn_t(strtoll(p, NULL, 10)); } @@ -1483,7 +1485,7 @@ bool backup_start() write_binlog_info(mysql_connection); } - if (have_flush_engine_logs) { + if (have_flush_engine_logs && !opt_no_lock) { msg_ts("Executing FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS...\n"); xb_mysql_query(mysql_connection, "FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS", false); diff --git a/extra/mariabackup/fil_cur.cc b/extra/mariabackup/fil_cur.cc index 258317bec05..27d957693ed 100644 --- a/extra/mariabackup/fil_cur.cc +++ b/extra/mariabackup/fil_cur.cc @@ -361,9 +361,14 @@ read_retry: page_no >= FSP_EXTENT_SIZE && page_no < FSP_EXTENT_SIZE * 3) { /* We ignore the doublewrite buffer pages */ - } else if (fil_space_verify_crypt_checksum( - page, cursor->page_size, - space->id, page_no)) { + } else if (mach_read_from_4( + page + + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION) + && space->crypt_data + && space->crypt_data->type + != CRYPT_SCHEME_UNENCRYPTED + && fil_space_verify_crypt_checksum( + page, cursor->page_size)) { ut_ad(mach_read_from_4(page + FIL_PAGE_SPACE_ID) == space->id); diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 59426b51127..75760ad352b 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -301,6 +301,7 @@ my_bool opt_decompress = FALSE; my_bool opt_remove_original; my_bool opt_lock_ddl_per_table = FALSE; +static my_bool opt_check_privileges; extern const char *innodb_checksum_algorithm_names[]; extern TYPELIB innodb_checksum_algorithm_typelib; @@ -832,7 +833,8 @@ enum options_xtrabackup OPT_PROTOCOL, OPT_LOCK_DDL_PER_TABLE, OPT_ROCKSDB_DATADIR, - OPT_BACKUP_ROCKSDB + OPT_BACKUP_ROCKSDB, + OPT_XTRA_CHECK_PRIVILEGES }; struct my_option xb_client_options[] = @@ -1385,6 +1387,10 @@ struct my_option xb_server_options[] = &xb_backup_rocksdb, &xb_backup_rocksdb, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 }, + {"check-privileges", OPT_XTRA_CHECK_PRIVILEGES, "Check database user " + "privileges fro the backup user", + &opt_check_privileges, &opt_check_privileges, + 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -5649,6 +5655,164 @@ append_defaults_group(const char *group, const char *default_groups[], ut_a(appended); } +static const char* +normalize_privilege_target_name(const char* name) +{ + if (strcmp(name, "*") == 0) { + return "\\*"; + } + else { + /* should have no regex special characters. */ + ut_ad(strpbrk(name, ".()[]*+?") == 0); + } + return name; +} + +/******************************************************************//** +Check if specific privilege is granted. +Uses regexp magic to check if requested privilege is granted for given +database.table or database.* or *.* +or if user has 'ALL PRIVILEGES' granted. +@return true if requested privilege is granted, false otherwise. */ +static bool +has_privilege(const std::list<std::string> &granted, + const char* required, + const char* db_name, + const char* table_name) +{ + char buffer[1000]; + regex_t priv_re; + regmatch_t tables_regmatch[1]; + bool result = false; + + db_name = normalize_privilege_target_name(db_name); + table_name = normalize_privilege_target_name(table_name); + + int written = snprintf(buffer, sizeof(buffer), + "GRANT .*(%s)|(ALL PRIVILEGES).* ON (\\*|`%s`)\\.(\\*|`%s`)", + required, db_name, table_name); + if (written < 0 || written == sizeof(buffer) + || regcomp(&priv_re, buffer, REG_EXTENDED)) { + exit(EXIT_FAILURE); + } + + typedef std::list<std::string>::const_iterator string_iter; + for (string_iter i = granted.begin(), e = granted.end(); i != e; ++i) { + int res = regexec(&priv_re, i->c_str(), + 1, tables_regmatch, 0); + + if (res != REG_NOMATCH) { + result = true; + break; + } + } + + xb_regfree(&priv_re); + return result; +} + +enum { + PRIVILEGE_OK = 0, + PRIVILEGE_WARNING = 1, + PRIVILEGE_ERROR = 2, +}; + +/******************************************************************//** +Check if specific privilege is granted. +Prints error message if required privilege is missing. +@return PRIVILEGE_OK if requested privilege is granted, error otherwise. */ +static +int check_privilege( + const std::list<std::string> &granted_priv, /* in: list of + granted privileges*/ + const char* required, /* in: required privilege name */ + const char* target_database, /* in: required privilege target + database name */ + const char* target_table, /* in: required privilege target + table name */ + int error = PRIVILEGE_ERROR) /* in: return value if privilege + is not granted */ +{ + if (!has_privilege(granted_priv, + required, target_database, target_table)) { + msg("%s: missing required privilege %s on %s.%s\n", + (error == PRIVILEGE_ERROR ? "Error" : "Warning"), + required, target_database, target_table); + return error; + } + return PRIVILEGE_OK; +} + + +/******************************************************************//** +Check DB user privileges according to the intended actions. + +Fetches DB user privileges, determines intended actions based on +command-line arguments and prints missing privileges. +May terminate application with EXIT_FAILURE exit code.*/ +static void +check_all_privileges() +{ + if (!mysql_connection) { + /* Not connected, no queries is going to be executed. */ + return; + } + + /* Fetch effective privileges. */ + std::list<std::string> granted_privileges; + MYSQL_ROW row = 0; + MYSQL_RES* result = xb_mysql_query(mysql_connection, "SHOW GRANTS", + true); + while ((row = mysql_fetch_row(result))) { + granted_privileges.push_back(*row); + } + mysql_free_result(result); + + int check_result = PRIVILEGE_OK; + bool reload_checked = false; + + /* FLUSH TABLES WITH READ LOCK */ + if (!opt_no_lock) + { + check_result |= check_privilege( + granted_privileges, + "RELOAD", "*", "*"); + reload_checked = true; + } + + if (!opt_no_lock) + { + check_result |= check_privilege( + granted_privileges, + "PROCESS", "*", "*"); + } + + /* KILL ... */ + if ((!opt_no_lock && (opt_kill_long_queries_timeout || opt_lock_ddl_per_table)) + /* START SLAVE SQL_THREAD */ + /* STOP SLAVE SQL_THREAD */ + || opt_safe_slave_backup) { + check_result |= check_privilege( + granted_privileges, + "SUPER", "*", "*", + PRIVILEGE_WARNING); + } + + /* SHOW MASTER STATUS */ + /* SHOW SLAVE STATUS */ + if (opt_galera_info || opt_slave_info + || (opt_no_lock && opt_safe_slave_backup)) { + check_result |= check_privilege(granted_privileges, + "REPLICATION CLIENT", "*", "*", + PRIVILEGE_WARNING); + } + + if (check_result & PRIVILEGE_ERROR) { + mysql_close(mysql_connection); + exit(EXIT_FAILURE); + } +} + bool xb_init() { @@ -5713,7 +5877,9 @@ xb_init() if (!get_mysql_vars(mysql_connection)) { return(false); } - + if (opt_check_privileges) { + check_all_privileges(); + } history_start_time = time(NULL); } |