From 49821f21ceef24ba51ffa4afe07953b2d71076f0 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 4 Dec 2024 17:51:23 +0100 Subject: [PATCH] MDEV-9158 post-merge fixes * format error messages (spaces, "bytes") * speed up "length too large" test from 12s to 70ms * fix it for --parallel * fix "named pipe" test to actually test a named pipe * add the standard header to tests, enable result log * fix for ASAN * read loop to workaround small (64K) pipe buffer size * clarified error message for the file too large --- .../r/filekeys_length_too_large.result | 15 +++++-- .../encryption/r/filekeys_named_pipe.result | 17 +++++--- .../t/filekeys_length_too_large.opt | 2 +- .../t/filekeys_length_too_large.test | 41 ++++++++----------- .../encryption/t/filekeys_named_pipe.opt | 2 +- .../encryption/t/filekeys_named_pipe.test | 32 ++++++++++----- plugin/file_key_management/parser.cc | 35 +++++++++++----- 7 files changed, 88 insertions(+), 56 deletions(-) diff --git a/mysql-test/suite/encryption/r/filekeys_length_too_large.result b/mysql-test/suite/encryption/r/filekeys_length_too_large.result index 1f2da85371c..a81c3c28087 100644 --- a/mysql-test/suite/encryption/r/filekeys_length_too_large.result +++ b/mysql-test/suite/encryption/r/filekeys_length_too_large.result @@ -1,8 +1,15 @@ +# +# MDEV-9158 file_key_management should support reading from a named pipe +# # Test checks if opening a too large key file, file key plugin will only read max key file size bytes and extra bytes will be ignored. -#Large key file will read max size bytes , which is 1MB -call mtr.add_suppression("Syntax error"); -call mtr.add_suppression("Invalid key"); +select seq,repeat(md5(seq), 200) +into outfile 'MYSQLTEST_VARDIR/tmp/filekeys-data-too-large.key' + fields terminated by ';' + from seq_1_to_1000; +#Large key file will read max size bytes, which is 1MB +call mtr.add_suppression("filekeys-data-too-large.key too large, must be less than 1048576 bytes"); call mtr.add_suppression("Plugin 'file_key_management' init function returned error"); call mtr.add_suppression("Plugin 'file_key_management' registration.*failed"); INSTALL SONAME 'file_key_management'; -FOUND 1 /read bytes: 1048576B/ in mysqld.1.err +ERROR HY000: File MYSQLTEST_VARDIR/tmp/filekeys-data-too-large.key too large, must be less than 1048576 bytes +FOUND 1 /filekeys-data-too-large.key too large, must be less than 1048576 bytes/ in mysqld.1.err diff --git a/mysql-test/suite/encryption/r/filekeys_named_pipe.result b/mysql-test/suite/encryption/r/filekeys_named_pipe.result index 3648bacb642..60a3b6dcaee 100644 --- a/mysql-test/suite/encryption/r/filekeys_named_pipe.result +++ b/mysql-test/suite/encryption/r/filekeys_named_pipe.result @@ -1,13 +1,20 @@ +# +# MDEV-9158 file_key_management should support reading from a named pipe +# +select seq,md5(seq) +into outfile 'MYSQLTEST_VARDIR/tmp/fifo-key.txt' + fields terminated by ';' + from seq_1_to_20000; INSTALL SONAME 'file_key_management'; Warnings: -Note 1 Read from MYSQL_TMP_DIR/fifo.key , read bytes: 105B, max key file size :1048576B -CREATE TABLE t1(c1 BIGINT NOT NULL, b CHAR(200)) ENGINE=INNODB ENCRYPTED=YES ENCRYPTION_KEY_ID=1; +Note 1 Read from MYSQLTEST_VARDIR/tmp/fifo.key, read bytes: 768894, max key file size: 1048576 bytes +CREATE TABLE t1(c1 BIGINT NOT NULL, b CHAR(200)) ENGINE=INNODB ENCRYPTED=YES ENCRYPTION_KEY_ID=1; SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `c1` bigint(20) NOT NULL, `b` char(200) DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci `ENCRYPTED`=YES `ENCRYPTION_KEY_ID`=1 +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci `ENCRYPTED`=YES `ENCRYPTION_KEY_ID`=1 INSERT t1 VALUES (12345, REPEAT('1234567890', 20)); ALTER TABLE t1 ENCRYPTION_KEY_ID=2; SHOW CREATE TABLE t1; @@ -15,14 +22,14 @@ Table Create Table t1 CREATE TABLE `t1` ( `c1` bigint(20) NOT NULL, `b` char(200) DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci `ENCRYPTED`=YES `ENCRYPTION_KEY_ID`=2 +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci `ENCRYPTED`=YES `ENCRYPTION_KEY_ID`=2 ALTER TABLE t1 ENCRYPTION_KEY_ID=3; SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `c1` bigint(20) NOT NULL, `b` char(200) DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci `ENCRYPTED`=YES `ENCRYPTION_KEY_ID`=3 +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci `ENCRYPTED`=YES `ENCRYPTION_KEY_ID`=3 # Reset mysqld DROP TABLE t1; UNINSTALL SONAME 'file_key_management'; diff --git a/mysql-test/suite/encryption/t/filekeys_length_too_large.opt b/mysql-test/suite/encryption/t/filekeys_length_too_large.opt index 42176fce987..5951f1afe1e 100644 --- a/mysql-test/suite/encryption/t/filekeys_length_too_large.opt +++ b/mysql-test/suite/encryption/t/filekeys_length_too_large.opt @@ -1 +1 @@ ---loose-file-key-management-filename=$MYSQL_TMP_DIR/filekeys-data-too-large.key \ No newline at end of file +--loose-file-key-management-filename=$MYSQLTEST_VARDIR/tmp/filekeys-data-too-large.key diff --git a/mysql-test/suite/encryption/t/filekeys_length_too_large.test b/mysql-test/suite/encryption/t/filekeys_length_too_large.test index e52b59cebd5..70f559c8a3f 100644 --- a/mysql-test/suite/encryption/t/filekeys_length_too_large.test +++ b/mysql-test/suite/encryption/t/filekeys_length_too_large.test @@ -1,33 +1,28 @@ --- source include/not_embedded.inc +--echo # +--echo # MDEV-9158 file_key_management should support reading from a named pipe +--echo # +--source include/not_embedded.inc +--source include/have_sequence.inc + --echo # Test checks if opening a too large key file, file key plugin will only read max key file size bytes and extra bytes will be ignored. -let $k=0; -while($k<1000){ - let $content=""; - let $i= 1; - while($i <= 100){ - let $num= `SELECT $i+$k*100`; - let $content=$content"$num;24e579b00c0f365a11761bdb9286a72a1148fa779d9c23dd55402627d0c87726"; - if($i<=99){ - let $content=$content"\n"; - } - inc $i; - } - exec echo -e $content >> $MYSQL_TMP_DIR/filekeys-data-too-large.key; - inc $k; -} ---echo #Large key file will read max size bytes , which is 1MB -let SEARCH_PATTERN=read bytes: 1048576B; -call mtr.add_suppression("Syntax error"); -call mtr.add_suppression("Invalid key"); +replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR; +eval select seq,repeat(md5(seq), 200) + into outfile '$MYSQLTEST_VARDIR/tmp/filekeys-data-too-large.key' + fields terminated by ';' + from seq_1_to_1000; + +--echo #Large key file will read max size bytes, which is 1MB +let SEARCH_PATTERN=filekeys-data-too-large.key too large, must be less than 1048576 bytes; +eval call mtr.add_suppression("$SEARCH_PATTERN"); call mtr.add_suppression("Plugin 'file_key_management' init function returned error"); call mtr.add_suppression("Plugin 'file_key_management' registration.*failed"); ---disable_result_log +replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR; --error 2 INSTALL SONAME 'file_key_management'; ---enable_result_log - --let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err --source include/search_pattern_in_file.inc + +--remove_file $MYSQLTEST_VARDIR/tmp/filekeys-data-too-large.key diff --git a/mysql-test/suite/encryption/t/filekeys_named_pipe.opt b/mysql-test/suite/encryption/t/filekeys_named_pipe.opt index 450e2c2bc62..a88da69fbac 100644 --- a/mysql-test/suite/encryption/t/filekeys_named_pipe.opt +++ b/mysql-test/suite/encryption/t/filekeys_named_pipe.opt @@ -1 +1 @@ ---loose-file-key-management-filename=$MYSQL_TMP_DIR/fifo.key \ No newline at end of file +--loose-file-key-management-filename=$MYSQLTEST_VARDIR/tmp/fifo.key diff --git a/mysql-test/suite/encryption/t/filekeys_named_pipe.test b/mysql-test/suite/encryption/t/filekeys_named_pipe.test index ccb0168b7dc..1dc289cb03e 100644 --- a/mysql-test/suite/encryption/t/filekeys_named_pipe.test +++ b/mysql-test/suite/encryption/t/filekeys_named_pipe.test @@ -1,18 +1,27 @@ +--echo # +--echo # MDEV-9158 file_key_management should support reading from a named pipe +--echo # +source include/not_windows.inc; +source include/have_innodb.inc; +source include/have_sequence.inc; # # Test read key from named pipe # -write_file $MYSQL_TMP_DIR/fifo.key; -1;11111111111111111111111111111111 -2;00000000000000000000000000000000 -3;22222222222222222222222222222222 -EOF ---sleep 3 - ---source include/have_innodb.inc ---replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR + +# large key file, >64K, which is the default value for F_SETPIPE_SZ +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval select seq,md5(seq) + into outfile '$MYSQLTEST_VARDIR/tmp/fifo-key.txt' + fields terminated by ';' + from seq_1_to_20000; + +exec mkfifo $MYSQLTEST_VARDIR/tmp/fifo.key; +system cat $MYSQLTEST_VARDIR/tmp/fifo-key.txt > $MYSQLTEST_VARDIR/tmp/fifo.key 2>/dev/null &; + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR INSTALL SONAME 'file_key_management'; -CREATE TABLE t1(c1 BIGINT NOT NULL, b CHAR(200)) ENGINE=INNODB ENCRYPTED=YES ENCRYPTION_KEY_ID=1; +CREATE TABLE t1(c1 BIGINT NOT NULL, b CHAR(200)) ENGINE=INNODB ENCRYPTED=YES ENCRYPTION_KEY_ID=1; SHOW CREATE TABLE t1; INSERT t1 VALUES (12345, REPEAT('1234567890', 20)); @@ -23,7 +32,8 @@ SHOW CREATE TABLE t1; --echo # Reset mysqld DROP TABLE t1; -remove_file $MYSQL_TMP_DIR/fifo.key; +remove_file $MYSQLTEST_VARDIR/tmp/fifo.key; +remove_file $MYSQLTEST_VARDIR/tmp/fifo-key.txt; UNINSTALL SONAME 'file_key_management'; --source include/restart_mysqld.inc diff --git a/plugin/file_key_management/parser.cc b/plugin/file_key_management/parser.cc index 6cf45b84981..65ff5a14705 100644 --- a/plugin/file_key_management/parser.cc +++ b/plugin/file_key_management/parser.cc @@ -180,7 +180,7 @@ bool Parser::read_filekey(const char *filekey, char *secret) { my_printf_error(EE_READ, "Cannot read %s, the filekey is too long, " - "max secret size is %dB ", + "max secret size is %d bytes", ME_ERROR_LOG, filekey, MAX_SECRET_SIZE); return 1; } @@ -314,7 +314,7 @@ int Parser::parse_line(char **line_ptr, keyentry *key) char* Parser::read_and_decrypt_file(const char *secret) { int f; - ssize_t file_size= 0; + size_t file_size= 0; if (!filename || !filename[0]) { my_printf_error(EE_CANT_OPEN_STREAM, "file-key-management-filename is not set", @@ -330,32 +330,45 @@ char* Parser::read_and_decrypt_file(const char *secret) } //Read file into buffer - uchar *buffer; - buffer= (uchar *) malloc((size_t) MAX_KEY_FILE_SIZE ); + uchar *buffer, *dst, *end; + buffer= (uchar *) malloc((size_t) MAX_KEY_FILE_SIZE+1 ); if (!buffer) { my_error(EE_OUTOFMEMORY, ME_ERROR_LOG | ME_FATAL, file_size); goto err1; } - file_size= read(f, buffer, MAX_KEY_FILE_SIZE); - if (file_size < 0) + + /* read loop in case fifo buffer size is too small */ + dst= buffer; + end= buffer + MAX_KEY_FILE_SIZE + 1; + for (ssize_t len= 1; len && dst < end; dst+= len) + { + if ((len= read(f, dst, (uint)(end - dst))) < 0) + { + my_printf_error(EE_READ, "Read from %s failed, errno %d", + ME_ERROR_LOG, filename, errno); + goto err2; + } + } + file_size= dst - buffer; + if (file_size > MAX_KEY_FILE_SIZE) { - my_printf_error(EE_READ, "Read from %s failed, errno %d", - ME_ERROR_LOG , filename, errno); + my_printf_error(EE_READ, "File %s too large, must be less than %d bytes", + ME_ERROR_LOG, filename, MAX_KEY_FILE_SIZE); goto err2; } my_printf_error(EE_ERROR_FIRST, - "Read from %s , read bytes: %zdB, max key file size :%dB ", + "Read from %s, read bytes: %zd, max key file size: %d bytes", ME_ERROR_LOG | ME_NOTE, filename, file_size, MAX_KEY_FILE_SIZE); // Check for file encryption uchar *decrypted; - if ((size_t)file_size > OpenSSL_prefix_len && strncmp((char*)buffer, OpenSSL_prefix, OpenSSL_prefix_len) == 0) + if (file_size > OpenSSL_prefix_len && strncmp((char*)buffer, OpenSSL_prefix, OpenSSL_prefix_len) == 0) { uchar key[OpenSSL_key_len]; uchar iv[OpenSSL_iv_len]; - decrypted= (uchar*)malloc((size_t)file_size); + decrypted= (uchar*)malloc(file_size+1); if (!decrypted) { my_error(EE_OUTOFMEMORY, ME_ERROR_LOG | ME_FATAL, file_size);