summaryrefslogtreecommitdiff
path: root/extra
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2018-12-18 09:15:41 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2018-12-18 09:15:41 +0200
commit45531949ae115f2ba7b9450cc2386653483211ba (patch)
tree22809f3919c711d5030d2d0e55be969a7bc67e84 /extra
parent36b7f8f4b0e46e06cfcc29c221430a5b998e3b3f (diff)
parented13a0d221256028299df4167280e97860ba2edc (diff)
downloadmariadb-git-45531949ae115f2ba7b9450cc2386653483211ba.tar.gz
Merge 10.2 into 10.3
Diffstat (limited to 'extra')
-rw-r--r--extra/innochecksum.cc11
-rw-r--r--extra/mariabackup/backup_copy.cc6
-rw-r--r--extra/mariabackup/fil_cur.cc11
-rw-r--r--extra/mariabackup/xtrabackup.cc170
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);
}