diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 3a15972acaf..3ba60a5643f 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -72,10 +72,6 @@ static my_bool non_blocking_api_enabled= 0; #include "../tests/nonblock-wrappers.h" #endif -/* Use cygwin for --exec and --system before 5.0 */ -#if MYSQL_VERSION_ID < 50000 -#define USE_CYGWIN -#endif #define MAX_VAR_NAME_LENGTH 256 #define MAX_COLUMNS 256 @@ -620,7 +616,6 @@ const char *get_errname_from_code (uint error_code); int multi_reg_replace(struct st_replace_regex* r,char* val); #ifdef _WIN32 -void free_tmp_sh_file(); void free_win_path_patterns(); #endif @@ -1458,7 +1453,6 @@ void free_used_memory() free_re(); my_free(read_command_buf); #ifdef _WIN32 - free_tmp_sh_file(); free_win_path_patterns(); #endif DBUG_VOID_RETURN; @@ -3190,33 +3184,6 @@ void do_source(struct st_command *command) } -#if defined _WIN32 - -#ifdef USE_CYGWIN -/* Variables used for temporary sh files used for emulating Unix on Windows */ -char tmp_sh_name[64], tmp_sh_cmd[70]; -#endif - -void init_tmp_sh_file() -{ -#ifdef USE_CYGWIN - /* Format a name for the tmp sh file that is unique for this process */ - my_snprintf(tmp_sh_name, sizeof(tmp_sh_name), "tmp_%d.sh", getpid()); - /* Format the command to execute in order to run the script */ - my_snprintf(tmp_sh_cmd, sizeof(tmp_sh_cmd), "sh %s", tmp_sh_name); -#endif -} - - -void free_tmp_sh_file() -{ -#ifdef USE_CYGWIN - my_delete(tmp_sh_name, MYF(0)); -#endif -} -#endif - - static void init_builtin_echo(void) { #ifdef _WIN32 @@ -3332,14 +3299,12 @@ void do_exec(struct st_command *command) } #ifdef _WIN32 -#ifndef USE_CYGWIN /* Replace /dev/null with NUL */ while(replace(&ds_cmd, "/dev/null", 9, "NUL", 3) == 0) ; /* Replace "closed stdout" with non existing output fd */ while(replace(&ds_cmd, ">&-", 3, ">&4", 3) == 0) ; -#endif #endif if (disable_result_log) @@ -3498,13 +3463,7 @@ int do_modify_var(struct st_command *command, int my_system(DYNAMIC_STRING* ds_cmd) { -#if defined _WIN32 && defined USE_CYGWIN - /* Dump the command into a sh script file and execute with system */ - str_to_file(tmp_sh_name, ds_cmd->str, ds_cmd->length); - return system(tmp_sh_cmd); -#else return system(ds_cmd->str); -#endif } @@ -3538,12 +3497,10 @@ void do_system(struct st_command *command) do_eval(&ds_cmd, command->first_argument, command->end, !is_windows); #ifdef _WIN32 -#ifndef USE_CYGWIN /* Replace /dev/null with NUL */ while(replace(&ds_cmd, "/dev/null", 9, "NUL", 3) == 0) ; #endif -#endif DBUG_PRINT("info", ("running system command '%s' as '%s'", @@ -5012,13 +4969,34 @@ int query_get_string(MYSQL* mysql, const char* query, } +#ifdef _WIN32 +#define SIGKILL 9 +#include static int my_kill(int pid, int sig) { - DBUG_PRINT("info", ("Killing server, pid: %d", pid)); -#ifdef _WIN32 -#define SIGKILL 9 /* ignored anyway, see below */ HANDLE proc; - if ((proc= OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE, pid)) == NULL) + if (sig == SIGABRT) + { + /* + Create a minidump. If process is being debugged, debug break + Otherwise, terminate. + */ + verbose_msg("Aborting %d",pid); + my_create_minidump(pid,TRUE); + proc= OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); + if(!proc) + return -1; + BOOL debugger_present; + if (CheckRemoteDebuggerPresent(proc,&debugger_present) && debugger_present) + { + if (DebugBreakProcess(proc)) + { + CloseHandle(proc); + return 0; + } + } + } + else if ((proc= OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE, pid)) == NULL) return -1; if (sig == 0) { @@ -5029,12 +5007,30 @@ static int my_kill(int pid, int sig) (void)TerminateProcess(proc, 201); CloseHandle(proc); return 1; -#else - return kill(pid, sig); -#endif } +/* Wait until process is gone, with timeout */ +static int wait_until_dead(int pid, int timeout) +{ + HANDLE proc= OpenProcess(SYNCHRONIZE, FALSE, pid); + if (!proc) + return 0; /* already dead */ + DBUG_ASSERT(timeout >= 0); + DBUG_ASSERT(timeout <= UINT_MAX/1000); + DWORD wait_result= WaitForSingleObject(proc, (DWORD)timeout*1000); + CloseHandle(proc); + return (int)wait_result; +} + +#else /* !_WIN32 */ + + +static int my_kill(int pid, int sig) +{ + DBUG_PRINT("info", ("Killing server, pid: %d", pid)); + return kill(pid, sig); +} /* Shutdown the server of current connection and @@ -5069,6 +5065,7 @@ static int wait_until_dead(int pid, int timeout) } DBUG_RETURN(1); // Did not die } +#endif /* _WIN32 */ void do_shutdown_server(struct st_command *command) @@ -9185,10 +9182,7 @@ int main(int argc, char **argv) init_builtin_echo(); #ifdef _WIN32 -#ifndef USE_CYGWIN is_windows= 1; -#endif - init_tmp_sh_file(); init_win_path_patterns(); #endif diff --git a/include/my_minidump.h b/include/my_minidump.h new file mode 100644 index 00000000000..0c0e843be8c --- /dev/null +++ b/include/my_minidump.h @@ -0,0 +1,25 @@ +/* Copyright (c) 2021, MariaDB Corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#include +#ifdef __cplusplus +extern "C" { +#endif + +BOOL my_create_minidump(DWORD pid, BOOL verbose); + +#ifdef __cplusplus +} +#endif diff --git a/libmariadb b/libmariadb index 42cb1e442c4..b99172386a7 160000 --- a/libmariadb +++ b/libmariadb @@ -1 +1 @@ -Subproject commit 42cb1e442c43902e2866bea38d15f2ed1f5d38b3 +Subproject commit b99172386a740ef0c8136e9a6cd7d9ad9a77b31f diff --git a/mysql-test/lib/My/SafeProcess/CMakeLists.txt b/mysql-test/lib/My/SafeProcess/CMakeLists.txt index eac1f1be8bd..0004a44982d 100644 --- a/mysql-test/lib/My/SafeProcess/CMakeLists.txt +++ b/mysql-test/lib/My/SafeProcess/CMakeLists.txt @@ -19,7 +19,8 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) IF (WIN32) ADD_EXECUTABLE(my_safe_process safe_process_win.cc) ADD_EXECUTABLE(my_safe_kill safe_kill_win.cc) - TARGET_LINK_LIBRARIES(my_safe_kill dbghelp psapi) + TARGET_INCLUDE_DIRECTORIES(my_safe_kill PRIVATE ${CMAKE_SOURCE_DIR}/include) + TARGET_LINK_LIBRARIES(my_safe_kill mysys psapi) ELSE() ADD_EXECUTABLE(my_safe_process safe_process.cc) ENDIF() diff --git a/mysql-test/lib/My/SafeProcess/safe_kill_win.cc b/mysql-test/lib/My/SafeProcess/safe_kill_win.cc index 4a9d5f2b8cc..375ed80b292 100644 --- a/mysql-test/lib/My/SafeProcess/safe_kill_win.cc +++ b/mysql-test/lib/My/SafeProcess/safe_kill_win.cc @@ -26,19 +26,7 @@ #include #include #include - -#ifdef _MSC_VER -/* Silence warning in OS header dbghelp.h */ -#pragma warning(push) -#pragma warning(disable : 4091) -#endif - -#include - -#ifdef _MSC_VER -/* Silence warning in OS header dbghelp.h */ -#pragma warning(pop) -#endif +#include #include #include @@ -64,106 +52,13 @@ static std::vector find_children(DWORD pid) return children; } -void dump_single_process(DWORD pid) -{ - HANDLE file = 0; - HANDLE process= 0; - DWORD size= MAX_PATH; - char path[MAX_PATH]; - char working_dir[MAX_PATH]; - char tmpname[MAX_PATH]; - char *filename= 0; - - process= OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); - if (!process) - { - fprintf(stderr, "safe_kill : cannot open process pid=%lu to create dump, last error %lu\n", - pid, GetLastError()); - goto exit; - } - - if (QueryFullProcessImageName(process, 0, path, &size) == 0) - { - fprintf(stderr, "safe_kill : cannot read process path for pid %lu, last error %lu\n", - pid, GetLastError()); - goto exit; - } - - filename= strrchr(path, '\\'); - if (filename) - { - filename++; - // We are not interested in dump of some proceses (my_safe_process.exe,cmd.exe) - // since they are only used to start up other programs. - // We're interested however in their children; - const char *exclude_programs[] = {"my_safe_process.exe","cmd.exe", 0}; - for(size_t i=0; exclude_programs[i]; i++) - if (_stricmp(filename, exclude_programs[i]) == 0) - goto exit; - } - else - filename= path; - - // Add .dmp extension - char *p; - if ((p= strrchr(filename, '.')) == 0) - p= filename + strlen(filename); - - strncpy(p, ".dmp", path + MAX_PATH - p); - - // f file with this name exist, generate unique name with .dmp extension - if (GetFileAttributes(filename) != INVALID_FILE_ATTRIBUTES) - { - if (!GetTempFileName(".", filename, 0, tmpname)) - { - fprintf(stderr, "GetTempFileName failed, last error %lu", GetLastError()); - goto exit; - } - strncat_s(tmpname, ".dmp", sizeof(tmpname)); - filename= tmpname; - } - - - if (!GetCurrentDirectory(MAX_PATH, working_dir)) - { - fprintf(stderr, "GetCurrentDirectory failed, last error %lu", GetLastError()); - goto exit; - } - - file= CreateFile(filename, GENERIC_READ | GENERIC_WRITE, - 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); - - if (file == INVALID_HANDLE_VALUE) - { - fprintf(stderr, "safe_kill : CreateFile() failed for file %s, working dir %s, last error = %lu\n", - filename, working_dir, GetLastError()); - goto exit; - } - - if (!MiniDumpWriteDump(process, pid, file, MiniDumpNormal, 0, 0, 0)) - { - fprintf(stderr, "Failed to write minidump to %s, working dir %s, last error %lu\n", - filename, working_dir, GetLastError()); - goto exit; - } - - fprintf(stderr, "Minidump written to %s, directory %s\n", filename, working_dir); - -exit: - if (process != 0 && process != INVALID_HANDLE_VALUE) - CloseHandle(process); - - if (file != 0 && file != INVALID_HANDLE_VALUE) - CloseHandle(file); -} - static int create_dump(DWORD pid, int recursion_depth= 5) { if (recursion_depth < 0) return 0; - dump_single_process(pid); + my_create_minidump(pid, TRUE); std::vector children= find_children(pid); for(size_t i=0; i < children.size(); i++) create_dump(children[i], recursion_depth -1); diff --git a/mysql-test/suite/galera/r/galera_fulltext.result b/mysql-test/suite/galera/r/galera_fulltext.result index 94780f235ad..12b29209f7e 100644 --- a/mysql-test/suite/galera/r/galera_fulltext.result +++ b/mysql-test/suite/galera/r/galera_fulltext.result @@ -38,34 +38,6 @@ DROP TABLE t1; DROP TABLE ten; connection node_1; SET @value=REPEAT (1,5001); -CREATE TABLE t (a VARCHAR(5000),FULLTEXT (a)) engine=innodb; -INSERT IGNORE INTO t VALUES(@value); -Warnings: -Warning 1265 Data truncated for column 'a' at row 1 -SELECT COUNT(*) FROM t; -COUNT(*) -1 -connection node_2; -SELECT COUNT(*) FROM t; -COUNT(*) -1 -connection node_1; -DROP TABLE t; -CREATE TABLE t (a VARCHAR(5000)) engine=innodb; -INSERT IGNORE INTO t VALUES(@value); -Warnings: -Warning 1265 Data truncated for column 'a' at row 1 -SELECT COUNT(*) FROM t; -COUNT(*) -1 -connection node_2; -SELECT COUNT(*) FROM t; -COUNT(*) -1 -connection node_1; -DROP TABLE t; -connection node_1; -SET @value=REPEAT (1,5001); CREATE TABLE t (a VARCHAR(5000),FULLTEXT (a)) engine=innodb DEFAULT CHARSET=utf8; INSERT IGNORE INTO t VALUES(@value); Warnings: diff --git a/mysql-test/suite/galera/t/galera_fulltext.test b/mysql-test/suite/galera/t/galera_fulltext.test index 25f4f83b7b7..76c29da4123 100644 --- a/mysql-test/suite/galera/t/galera_fulltext.test +++ b/mysql-test/suite/galera/t/galera_fulltext.test @@ -60,29 +60,6 @@ SELECT COUNT(f1) = 1000 FROM t1 WHERE MATCH(f1) AGAINST ('abcdefjhk'); DROP TABLE t1; DROP TABLE ten; -# -# MDEV-24978 : SIGABRT in __libc_message -# ---connection node_1 -SET @value=REPEAT (1,5001); -CREATE TABLE t (a VARCHAR(5000),FULLTEXT (a)) engine=innodb; -INSERT IGNORE INTO t VALUES(@value); -SELECT COUNT(*) FROM t; - ---connection node_2 -SELECT COUNT(*) FROM t; - ---connection node_1 -DROP TABLE t; -CREATE TABLE t (a VARCHAR(5000)) engine=innodb; -INSERT IGNORE INTO t VALUES(@value); -SELECT COUNT(*) FROM t; - ---connection node_2 -SELECT COUNT(*) FROM t; - ---connection node_1 -DROP TABLE t; # # Case 2: UTF-8 diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt index 92269538c58..45146bc3d49 100644 --- a/mysys/CMakeLists.txt +++ b/mysys/CMakeLists.txt @@ -55,6 +55,7 @@ IF (WIN32) my_winerr.c my_winfile.c my_conio.c + my_minidump.cc my_win_popen.cc) ENDIF() @@ -173,7 +174,7 @@ IF(HAVE_BFD_H) ENDIF(HAVE_BFD_H) IF (WIN32) - TARGET_LINK_LIBRARIES(mysys IPHLPAPI) + TARGET_LINK_LIBRARIES(mysys iphlpapi dbghelp) ENDIF(WIN32) # Need explicit pthread for gcc -fsanitize=address diff --git a/mysys/my_minidump.cc b/mysys/my_minidump.cc new file mode 100644 index 00000000000..d81aab2f764 --- /dev/null +++ b/mysys/my_minidump.cc @@ -0,0 +1,115 @@ +/* Copyright (c) 2021, MariaDB Corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#include +#include +#include +#include + +#define VERBOSE(fmt,...) \ + if (verbose) { fprintf(stderr, "my_create_minidump : " fmt,__VA_ARGS__); } + +extern "C" BOOL my_create_minidump(DWORD pid, BOOL verbose) +{ + HANDLE file = 0; + HANDLE process= 0; + DWORD size= MAX_PATH; + char path[MAX_PATH]; + char working_dir[MAX_PATH]; + char tmpname[MAX_PATH]; + char *filename= 0; + bool ret= FALSE; + process= OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); + if (!process) + { + VERBOSE("cannot open process pid=%lu to create dump, last error %lu\n", + pid, GetLastError()); + goto exit; + } + + if (QueryFullProcessImageName(process, 0, path, &size) == 0) + { + VERBOSE("cannot read process path for pid %lu, last error %lu\n", + pid, GetLastError()); + goto exit; + } + + filename= strrchr(path, '\\'); + if (filename) + { + filename++; + // We are not interested in dump of some proceses (my_safe_process.exe,cmd.exe) + // since they are only used to start up other programs. + // We're interested however in their children; + const char *exclude_programs[] = {"my_safe_process.exe","cmd.exe", 0}; + for(size_t i=0; exclude_programs[i]; i++) + if (_stricmp(filename, exclude_programs[i]) == 0) + goto exit; + } + else + filename= path; + + // Add .dmp extension + char *p; + if ((p= strrchr(filename, '.')) == 0) + p= filename + strlen(filename); + + strncpy(p, ".dmp", path + MAX_PATH - p); + + // Íf file with this name exist, generate unique name with .dmp extension + if (GetFileAttributes(filename) != INVALID_FILE_ATTRIBUTES) + { + if (!GetTempFileName(".", filename, 0, tmpname)) + { + fprintf(stderr, "GetTempFileName failed, last error %lu", GetLastError()); + goto exit; + } + strncat_s(tmpname, ".dmp", sizeof(tmpname)); + filename= tmpname; + } + + if (!GetCurrentDirectory(MAX_PATH, working_dir)) + { + VERBOSE("GetCurrentDirectory failed, last error %lu", GetLastError()); + goto exit; + } + + file= CreateFile(filename, GENERIC_READ | GENERIC_WRITE, + 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + + if (file == INVALID_HANDLE_VALUE) + { + VERBOSE("CreateFile() failed for file %s, working dir %s, last error = %lu\n", + filename, working_dir, GetLastError()); + goto exit; + } + + if (!MiniDumpWriteDump(process, pid, file, MiniDumpNormal, 0, 0, 0)) + { + VERBOSE("Failed to write minidump to %s, working dir %s, last error %lu\n", + filename, working_dir, GetLastError()); + goto exit; + } + + VERBOSE("Minidump written to %s, directory %s\n", filename, working_dir); + ret= TRUE; +exit: + if (process != 0 && process != INVALID_HANDLE_VALUE) + CloseHandle(process); + + if (file != 0 && file != INVALID_HANDLE_VALUE) + CloseHandle(file); + return ret; +} diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh index 67244a7c622..a1293fcb749 100644 --- a/scripts/wsrep_sst_common.sh +++ b/scripts/wsrep_sst_common.sh @@ -1065,8 +1065,9 @@ check_for_dhparams() # verify_ca_matches_cert() { - local ca_path="$1" - local cert_path="$2" + local ca="$1" + local cert="$2" + local path=${3:-0} # If the openssl utility is not installed, then # we will not do this certificate check: @@ -1075,8 +1076,15 @@ verify_ca_matches_cert() return fi - if ! "$OPENSSL_BINARY" verify -verbose -CAfile "$ca_path" "$cert_path" >/dev/null 2>&1 - then + local not_match=0 + + if [ $path -eq 0 ]; then + "$OPENSSL_BINARY" verify -verbose -CAfile "$ca" "$cert" >/dev/null 2>&1 || not_match=1 + else + "$OPENSSL_BINARY" verify -verbose -CApath "$ca" "$cert" >/dev/null 2>&1 || not_match=1 + fi + + if [ $not_match -eq 1 ]; then wsrep_log_error "******** FATAL ERROR ********************************************" wsrep_log_error "* The certifcate and CA (certificate authority) do not match. *" wsrep_log_error "* It does not appear that the certificate was issued by the CA. *" diff --git a/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh index 54632e5f79b..3fe3bf5c206 100644 --- a/scripts/wsrep_sst_mariabackup.sh +++ b/scripts/wsrep_sst_mariabackup.sh @@ -34,6 +34,7 @@ ssyslog="" ssystag="" BACKUP_PID="" tcert="" +tpath=0 tpem="" tkey="" tmode="DISABLED" @@ -85,7 +86,6 @@ readonly SECRET_TAG="secret" # Required for backup locks # For backup locks it is 1 sent by joiner -# 5.6.21 PXC and later can't donate to an older joiner sst_ver=1 if [ -n "$(command -v pv)" ] && pv --help | grep -qw -- '-F'; then @@ -339,64 +339,83 @@ get_transfer() fi fi + CN_option=",commonname=''" + if [ $encrypt -eq 2 ]; then wsrep_log_info "Using openssl based encryption with socat: with crt and pem" if [ -z "$tpem" -o -z "$tcert" ]; then - wsrep_log_error "Both PEM and CRT files required" + wsrep_log_error \ + "Both PEM file and CRT file (or path) are required" exit 22 fi if [ ! -r "$tpem" -o ! -r "$tcert" ]; then - wsrep_log_error "Both PEM and CRT files must be readable" + wsrep_log_error \ + "Both PEM file and CRT file (or path) must be readable" exit 22 fi - verify_ca_matches_cert "$tcert" "$tpem" - tcmd="$tcmd,cert='$tpem',cafile='$tcert'$sockopt" + verify_ca_matches_cert "$tcert" "$tpem" $tpath + if [ $tpath -eq 0 ]; then + tcmd="$tcmd,cert='$tpem',cafile='$tcert'" + else + tcmd="$tcmd,cert='$tpem',capath='$tcert'" + fi stagemsg="$stagemsg-OpenSSL-Encrypted-2" - wsrep_log_info "$action with cert=$tpem, cafile=$tcert" + wsrep_log_info "$action with cert=$tpem, ca=$tcert" elif [ $encrypt -eq 3 -o $encrypt -eq 4 ]; then wsrep_log_info "Using openssl based encryption with socat: with key and crt" if [ -z "$tpem" -o -z "$tkey" ]; then - wsrep_log_error "Both certificate and key files required" + wsrep_log_error "Both certificate file (or path) " \ + "and key file are required" exit 22 fi if [ ! -r "$tpem" -o ! -r "$tkey" ]; then - wsrep_log_error "Both certificate and key files must be readable" + wsrep_log_error "Both certificate file (or path) " \ + "and key file must be readable" exit 22 fi verify_cert_matches_key "$tpem" "$tkey" stagemsg="$stagemsg-OpenSSL-Encrypted-3" if [ -z "$tcert" ]; then if [ $encrypt -eq 4 ]; then - wsrep_log_error "Peer certificate required if encrypt=4" + wsrep_log_error \ + "Peer certificate file (or path) required if encrypt=4" exit 22 fi # no verification - tcmd="$tcmd,cert='$tpem',key='$tkey',verify=0$sockopt" + CN_option="" + tcmd="$tcmd,cert='$tpem',key='$tkey',verify=0" wsrep_log_info "$action with cert=$tpem, key=$tkey, verify=0" else # CA verification if [ ! -r "$tcert" ]; then - wsrep_log_error "Certificate file must be readable" + wsrep_log_error "Certificate file or path must be readable" exit 22 fi - verify_ca_matches_cert "$tcert" "$tpem" + verify_ca_matches_cert "$tcert" "$tpem" $tpath if [ -n "$WSREP_SST_OPT_REMOTE_USER" ]; then CN_option=",commonname='$WSREP_SST_OPT_REMOTE_USER'" - elif [ $encrypt -eq 4 ]; then + elif [ "$WSREP_SST_OPT_ROLE" = 'joiner' -o $encrypt -eq 4 ] + then CN_option=",commonname=''" elif is_local_ip "$WSREP_SST_OPT_HOST_UNESCAPED"; then CN_option=',commonname=localhost' else CN_option=",commonname='$WSREP_SST_OPT_HOST_UNESCAPED'" fi - tcmd="$tcmd,cert='$tpem',key='$tkey',cafile='$tcert'$CN_option$sockopt" - wsrep_log_info "$action with cert=$tpem, key=$tkey, cafile=$tcert" + if [ $tpath -eq 0 ]; then + tcmd="$tcmd,cert='$tpem',key='$tkey',cafile='$tcert'" + else + tcmd="$tcmd,cert='$tpem',key='$tkey',capath='$tcert'" + fi + wsrep_log_info "$action with cert=$tpem, key=$tkey, ca=$tcert" fi else wsrep_log_info "Unknown encryption mode: encrypt=$encrypt" exit 22 fi + tcmd="$tcmd$CN_option$sockopt" + if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then tcmd="$tcmd stdio" fi @@ -473,6 +492,12 @@ check_server_ssl_config() "of the tca, tcert and/or tkey in the [sst] section" fi fi + if [ -n "$tcert" ]; then + tcert=$(trim_string "$tcert") + if [ "${tcert%/}" != "$tcert" ]; then + tpath=1 + fi + fi } read_cnf() diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index e16ed75cb16..ad9688011e1 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -236,11 +236,18 @@ check_server_ssl_config() SSLMODE=$(parse_cnf "$SST_SECTIONS" 'ssl-mode' | tr [:lower:] [:upper:]) # no old-style SSL config in [sst], check for new one: -if [ -z "$SSTKEY" -a -z "$SSTCERT" -a -z "$SSTCA" ] -then +if [ -z "$SSTKEY" -a -z "$SSTCERT" -a -z "$SSTCA" ]; then check_server_ssl_config fi +SSTPATH=0 +if [ -n "$SSTCA" ]; then + SSTCA=$(trim_string "$SSTCA") + if [ "${SSTCA%/}" != "$SSTCA" ]; then + SSTPATH=1 + fi +fi + if [ -z "$SSLMODE" ]; then # Implicit verification if CA is set and the SSL mode # is not specified by user: @@ -254,9 +261,19 @@ if [ -z "$SSLMODE" ]; then fi fi -if [ -n "$SSTCA" ] -then - CAFILE_OPT="CAfile = $SSTCA" +if [ -n "$SSTCERT" -a -n "$SSTKEY" ]; then + verify_cert_matches_key "$SSTCERT" "$SSTKEY" +fi + +if [ -n "$SSTCA" ]; then + if [ $SSTPATH -eq 0 ]; then + CAFILE_OPT="CAfile = $SSTCA" + else + CAFILE_OPT="CApath = $SSTCA" + fi + if [ -n "$SSTCERT" ]; then + verify_ca_matches_cert "$SSTCA" "$SSTCERT" $SSTPATH + fi else CAFILE_OPT="" fi @@ -272,38 +289,38 @@ then ;; 'VERIFY_CA') VERIFY_OPT='verifyChain = yes' - if [ -n "$WSREP_SST_OPT_REMOTE_USER" ]; then - CHECK_OPT="checkHost = $WSREP_SST_OPT_REMOTE_USER" - else - # check if the address is an ip-address (v4 or v6): - if echo "$WSREP_SST_OPT_HOST_UNESCAPED" | \ - grep -q -E '^([0-9]+(\.[0-9]+){3}|[0-9a-fA-F]*(\:[0-9a-fA-F]*)+)$' - then - CHECK_OPT="checkIP = $WSREP_SST_OPT_HOST_UNESCAPED" - else - CHECK_OPT="checkHost = $WSREP_SST_OPT_HOST" - fi - if is_local_ip "$WSREP_SST_OPT_HOST_UNESCAPED"; then - CHECK_OPT_LOCAL="checkHost = localhost" - fi - fi ;; *) wsrep_log_error "Unrecognized ssl-mode option: '$SSLMODE'" exit 22 # EINVAL ;; esac - if [ -z "$CAFILE_OPT" ]; then - wsrep_log_error "Can't have ssl-mode='$SSLMODE' without CA file" + if [ -z "$SSTCA" ]; then + wsrep_log_error "Can't have ssl-mode='$SSLMODE' without CA file or path" exit 22 # EINVAL fi + if [ -n "$WSREP_SST_OPT_REMOTE_USER" ]; then + CHECK_OPT="checkHost = $WSREP_SST_OPT_REMOTE_USER" + elif [ "$WSREP_SST_OPT_ROLE" = 'donor' ]; then + # check if the address is an ip-address (v4 or v6): + if echo "$WSREP_SST_OPT_HOST_UNESCAPED" | \ + grep -q -E '^([0-9]+(\.[0-9]+){3}|[0-9a-fA-F]*(\:[0-9a-fA-F]*)+)$' + then + CHECK_OPT="checkIP = $WSREP_SST_OPT_HOST_UNESCAPED" + else + CHECK_OPT="checkHost = $WSREP_SST_OPT_HOST" + fi + if is_local_ip "$WSREP_SST_OPT_HOST_UNESCAPED"; then + CHECK_OPT_LOCAL="checkHost = localhost" + fi + fi fi STUNNEL="" if [ -n "$SSLMODE" -a "$SSLMODE" != 'DISABLED' ]; then STUNNEL_BIN="$(command -v stunnel)" if [ -n "$STUNNEL_BIN" ]; then - wsrep_log_info "Using stunnel for SSL encryption: CAfile: '$SSTCA', ssl-mode='$SSLMODE'" + wsrep_log_info "Using stunnel for SSL encryption: CA: '$SSTCA', ssl-mode='$SSLMODE'" STUNNEL="$STUNNEL_BIN $STUNNEL_CONF" fi fi diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 7db11938e4b..405c6284df1 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -6167,8 +6167,8 @@ wsrep_innobase_mysql_sort( case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_VARCHAR: { - uchar *tmp_str; - ulint tmp_length; + uchar tmp_str[REC_VERSION_56_MAX_INDEX_COL_LEN] = {'\0'}; + ulint tmp_length = REC_VERSION_56_MAX_INDEX_COL_LEN; /* Use the charset number to pick the right charset struct for the comparison. Since the MySQL function get_charset may be @@ -6191,12 +6191,7 @@ wsrep_innobase_mysql_sort( } } - // Note that strnxfrm may change length of string - tmp_length= charset->coll->strnxfrmlen(charset, str_length); - tmp_length= tmp_length * charset->mbmaxlen; - tmp_length= ut_max(str_length, tmp_length) + charset->mbmaxlen; - tmp_str= static_cast(ut_malloc_nokey(tmp_length)); - ut_ad(str_length <= tmp_length); + ut_a(str_length <= tmp_length); memcpy(tmp_str, str, str_length); tmp_length = charset->strnxfrm(str, str_length, @@ -6220,7 +6215,6 @@ wsrep_innobase_mysql_sort( ret_length = tmp_length; } - ut_free(tmp_str); break; } case MYSQL_TYPE_DECIMAL : @@ -6566,7 +6560,7 @@ wsrep_store_key_val_for_row( THD* thd, TABLE* table, uint keynr, /*!< in: key number */ - uchar* buff, /*!< in/out: buffer for the key value (in MySQL + char* buff, /*!< in/out: buffer for the key value (in MySQL format) */ uint buff_len,/*!< in: buffer length */ const uchar* record, @@ -6575,7 +6569,7 @@ wsrep_store_key_val_for_row( KEY* key_info = table->key_info + keynr; KEY_PART_INFO* key_part = key_info->key_part; KEY_PART_INFO* end = key_part + key_info->user_defined_key_parts; - uchar* buff_start = buff; + char* buff_start = buff; enum_field_types mysql_type; Field* field; ulint buff_space = buff_len; @@ -6586,7 +6580,7 @@ wsrep_store_key_val_for_row( *key_is_null = true; for (; key_part != end; key_part++) { - uchar *sorted = nullptr; + uchar sorted[REC_VERSION_56_MAX_INDEX_COL_LEN] = {'\0'}; bool part_is_null = false; if (key_part->null_bit) { @@ -6665,14 +6659,10 @@ wsrep_store_key_val_for_row( true_len = key_len; } - const ulint max_len = true_len; - sorted= static_cast(ut_malloc_nokey(max_len+1)); memcpy(sorted, data, true_len); true_len = wsrep_innobase_mysql_sort( mysql_type, cs->number, sorted, true_len, - max_len); - ut_ad(true_len <= max_len); - + REC_VERSION_56_MAX_INDEX_COL_LEN); if (wsrep_protocol_version > 1) { /* Note that we always reserve the maximum possible length of the true VARCHAR in the key value, though @@ -6757,13 +6747,11 @@ wsrep_store_key_val_for_row( true_len = key_len; } - const ulint max_len= true_len; - sorted= static_cast(ut_malloc_nokey(max_len+1)); memcpy(sorted, blob_data, true_len); true_len = wsrep_innobase_mysql_sort( mysql_type, cs->number, sorted, true_len, - max_len); - ut_ad(true_len <= max_len); + REC_VERSION_56_MAX_INDEX_COL_LEN); + /* Note that we always reserve the maximum possible length of the BLOB prefix in the key value. */ @@ -6839,14 +6827,10 @@ wsrep_store_key_val_for_row( cs->mbmaxlen), &error); } - - const ulint max_len = true_len; - sorted= static_cast(ut_malloc_nokey(max_len+1)); memcpy(sorted, src_start, true_len); true_len = wsrep_innobase_mysql_sort( mysql_type, cs->number, sorted, true_len, - max_len); - ut_ad(true_len <= max_len); + REC_VERSION_56_MAX_INDEX_COL_LEN); if (true_len > buff_space) { fprintf (stderr, @@ -6861,11 +6845,6 @@ wsrep_store_key_val_for_row( buff += true_len; buff_space -= true_len; } - - if (sorted) { - ut_free(sorted); - sorted= NULL; - } } ut_a(buff <= buff_start + buff_len); @@ -9890,7 +9869,7 @@ wsrep_append_key( THD *thd, trx_t *trx, TABLE_SHARE *table_share, - const uchar* key, + const char* key, uint16_t key_len, Wsrep_service_key_type key_type /*!< in: access type of this key (shared, exclusive, semi...) */ @@ -10001,8 +9980,8 @@ ha_innobase::wsrep_append_keys( } if (wsrep_protocol_version == 0) { - uchar keyval[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; - uchar *key = &keyval[0]; + char keyval[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; + char *key = &keyval[0]; bool is_null; auto len = wsrep_store_key_val_for_row( @@ -10043,12 +10022,12 @@ ha_innobase::wsrep_append_keys( /* keyval[] shall contain an ordinal number at byte 0 and the actual key data shall be written at byte 1. Hence the total data length is the key length + 1 */ - uchar keyval0[WSREP_MAX_SUPPORTED_KEY_LENGTH+1]= {'\0'}; - uchar keyval1[WSREP_MAX_SUPPORTED_KEY_LENGTH+1]= {'\0'}; - keyval0[0] = (uchar)i; - keyval1[0] = (uchar)i; - uchar* key0 = &keyval0[1]; - uchar* key1 = &keyval1[1]; + char keyval0[WSREP_MAX_SUPPORTED_KEY_LENGTH+1]= {'\0'}; + char keyval1[WSREP_MAX_SUPPORTED_KEY_LENGTH+1]= {'\0'}; + keyval0[0] = (char)i; + keyval1[0] = (char)i; + char* key0 = &keyval0[1]; + char* key1 = &keyval1[1]; if (!tab) { WSREP_WARN("MariaDB-InnoDB key mismatch %s %s", @@ -10128,16 +10107,18 @@ ha_innobase::wsrep_append_keys( wsrep_calc_row_hash(digest, record0, table, m_prebuilt); if (int rcode = wsrep_append_key(thd, trx, table_share, - digest, 16, key_type)) { + reinterpret_cast + (digest), 16, key_type)) { DBUG_RETURN(rcode); } if (record1) { wsrep_calc_row_hash( digest, record1, table, m_prebuilt); - if (int rcode = wsrep_append_key(thd, trx, table_share, - digest, 16, - key_type)) { + if (int rcode = wsrep_append_key( + thd, trx, table_share, + reinterpret_cast(digest), 16, + key_type)) { DBUG_RETURN(rcode); } } diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh index cbd6b472148..d2c824697d1 100644 --- a/support-files/mysql.server.sh +++ b/support-files/mysql.server.sh @@ -91,16 +91,15 @@ datadir_set= # # Use LSB init script functions for printing messages, if possible -# +# Include non-LSB RedHat init functions to make systemctl redirect work +init_functions="/etc/init.d/functions" lsb_functions="/lib/lsb/init-functions" -if test -f $lsb_functions ; then +if test -f $lsb_functions; then . $lsb_functions -else - # Include non-LSB RedHat init functions to make systemctl redirect work - init_functions="/etc/init.d/functions" - if test -f $init_functions; then - . $init_functions - fi +fi + +if test -f $init_functions; then + . $init_functions log_success_msg() { echo " SUCCESS! $@"