diff --git a/projects/mysql-server/Dockerfile b/projects/mysql-server/Dockerfile new file mode 100644 index 000000000..d2ee3fb07 --- /dev/null +++ b/projects/mysql-server/Dockerfile @@ -0,0 +1,25 @@ +# Copyright 2018 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +################################################################################ + +FROM gcr.io/oss-fuzz-base/base-builder +MAINTAINER secalert_us@oracle.com +RUN apt-get update +RUN apt-get install -y build-essential libssl-dev libncurses5-dev libncursesw5-dev make cmake perl bison pkg-config +RUN git clone --depth 1 https://github.com/mysql/mysql-server +WORKDIR $SRC +COPY build.sh $SRC/ +COPY fix.diff $SRC/ +COPY targets $SRC/mysql-server/fuzz \ No newline at end of file diff --git a/projects/mysql-server/build.sh b/projects/mysql-server/build.sh new file mode 100644 index 000000000..4cfc3b416 --- /dev/null +++ b/projects/mysql-server/build.sh @@ -0,0 +1,31 @@ + +#!/bin/bash -eu +# Copyright 2018 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +################################################################################ + +cd mysql-server +git apply ../fix.diff +mkdir build +cd build +cmake .. -Dprotobuf_BUILD_SHARED_LIBS=OFF -DDOWNLOAD_BOOST=1 -DWITH_BOOST=. -DWITH_SSL=system -DFUZZING=1 -DCMAKE_INSTALL_PREFIX=$OUT/mysql +make install +cp $OUT/mysql/bin/fuzz* $OUT/ +cp ../fuzz/fuzz*.options $OUT/ +cp ../fuzz/fuzz*.dict $OUT/ +cp ../fuzz/init*.sql $OUT/ + +rm -Rf $OUT/mysql/data +$OUT/mysql/bin/mysqld --user=root --initialize-insecure --log-error-verbosity=5 --skip-ssl --datadir=$OUT/mysql/data --basedir=$OUT/mysql/ diff --git a/projects/mysql-server/fix.diff b/projects/mysql-server/fix.diff new file mode 100644 index 000000000..562d1b38b --- /dev/null +++ b/projects/mysql-server/fix.diff @@ -0,0 +1,414 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 17939f7c6f4..e05deb5911e 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -517,6 +517,7 @@ IF(WITH_JEMALLOC) + STRING_APPEND(CMAKE_CXX_FLAGS " -fno-builtin-realloc -fno-builtin-free") + ENDIF() + ++OPTION(FUZZING "Fuzzing" OFF) + OPTION(ENABLED_PROFILING "Enable profiling" ON) + OPTION(WITHOUT_SERVER OFF) + IF(UNIX) +@@ -1324,6 +1325,10 @@ IF(NOT WITHOUT_SERVER) + ADD_SUBDIRECTORY(sql) + ENDIF() + ++IF (FUZZING) ++ ADD_SUBDIRECTORY(fuzz) ++ENDIF() ++ + # scripts/mysql_config depends on client and server targets loaded above. + # It is referenced by some of the directories below, so we insert it here. + ADD_SUBDIRECTORY(scripts) +diff --git a/include/mysql.h b/include/mysql.h +index 1f499e9d9e5..a85c181ae78 100644 +--- a/include/mysql.h ++++ b/include/mysql.h +@@ -261,7 +261,8 @@ enum mysql_protocol_type { + MYSQL_PROTOCOL_TCP, + MYSQL_PROTOCOL_SOCKET, + MYSQL_PROTOCOL_PIPE, +- MYSQL_PROTOCOL_MEMORY ++ MYSQL_PROTOCOL_MEMORY, ++ MYSQL_PROTOCOL_FUZZ + }; + + enum mysql_ssl_mode { +diff --git a/include/violite.h b/include/violite.h +index 9f9d6e62e2e..32bed2eeb30 100644 +--- a/include/violite.h ++++ b/include/violite.h +@@ -106,12 +106,14 @@ enum enum_vio_type : int { + */ + VIO_TYPE_PLUGIN = 7, + ++ VIO_TYPE_FUZZ = 8, ++ + FIRST_VIO_TYPE = VIO_TYPE_TCPIP, + /* + If a new type is added, please update LAST_VIO_TYPE. In addition, please + change get_vio_type_name() in vio/vio.c to return correct name for it. + */ +- LAST_VIO_TYPE = VIO_TYPE_PLUGIN ++ LAST_VIO_TYPE = VIO_TYPE_FUZZ + }; + + /** +@@ -449,4 +451,20 @@ struct Vio { + #define SSL_handle void * + #endif + ++ ++//Vio fuzzing ++bool vio_connect_fuzz(MYSQL_VIO vio, struct sockaddr *addr, socklen_t len, ++ int timeout); ++int vio_socket_timeout_fuzz(Vio *vio, uint which, bool b); ++void sock_initfuzz(const uint8_t *Data, size_t Size); ++size_t vio_read_buff_fuzz(Vio *vio, uchar *buf, size_t size); ++size_t vio_write_buff_fuzz(Vio *vio, const uchar *buf, size_t size); ++bool vio_is_connected_fuzz(Vio *vio); ++bool vio_was_timeout_fuzz(Vio *vio); ++int vio_shutdown_fuzz(Vio *vio); ++int vio_keepalive_fuzz(Vio *vio, bool set_keep_alive); ++int vio_io_wait_fuzz(Vio *vio, enum enum_vio_io_event event, int timeout); ++int vio_fastsend_fuzz(Vio *vio); ++bool vio_should_retry_fuzz(Vio *vio); ++ + #endif /* vio_violite_h_ */ +diff --git a/libmysql/CMakeLists.txt b/libmysql/CMakeLists.txt +index 52b9b61271f..e452fc202a5 100644 +--- a/libmysql/CMakeLists.txt ++++ b/libmysql/CMakeLists.txt +@@ -320,7 +320,7 @@ IF(UNIX) + ENDIF() + + GET_TARGET_PROPERTY(libmysql_link_flags libmysql LINK_FLAGS) +- IF(LINK_FLAG_NO_UNDEFINED) ++ IF(LINK_FLAG_NO_UNDEFINED AND NOT FUZZING) + STRING_APPEND(libmysql_link_flags + " ${LINK_FLAG_NO_UNDEFINED}") + STRING_APPEND(libmysql_link_flags +diff --git a/mysys/my_rnd.cc b/mysys/my_rnd.cc +index fa96e35eb02..e03ee47c220 100644 +--- a/mysys/my_rnd.cc ++++ b/mysys/my_rnd.cc +@@ -51,6 +51,9 @@ + */ + + double my_rnd(struct rand_struct *rand_st) { ++#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION ++ return 65.43; ++#endif + rand_st->seed1 = (rand_st->seed1 * 3 + rand_st->seed2) % rand_st->max_value; + rand_st->seed2 = (rand_st->seed1 + rand_st->seed2 + 33) % rand_st->max_value; + return (((double)rand_st->seed1) / rand_st->max_value_dbl); +@@ -67,6 +70,12 @@ Fill a buffer with random bytes using the SSL library routines + */ + int my_rand_buffer(unsigned char *buffer, size_t buffer_size) { + int rc; ++#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION ++ for (size_t i = 0; i < buffer_size; i++) ++ buffer[i] = i; ++ return 0; ++#endif ++ + rc = RAND_bytes(buffer, (int)buffer_size); + + if (!rc) { +@@ -88,6 +97,9 @@ int my_rand_buffer(unsigned char *buffer, size_t buffer_size) { + double my_rnd_ssl(bool *failed) { + unsigned int res; + ++#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION ++ return 34.56; ++#endif + if (my_rand_buffer((unsigned char *)&res, sizeof(res))) { + *failed = true; + return 0; +diff --git a/sql-common/client.cc b/sql-common/client.cc +index f5e760cc37d..09037a9e236 100644 +--- a/sql-common/client.cc ++++ b/sql-common/client.cc +@@ -5850,6 +5850,12 @@ static mysql_state_machine_status csm_begin_connect(mysql_async_connect *ctx) { + } + } + #endif /* _WIN32 */ ++if (!net->vio && ++ (mysql->options.protocol == MYSQL_PROTOCOL_FUZZ)) { ++ net->vio = ++ vio_new(0, VIO_TYPE_FUZZ, 0); ++ ctx->host_info = (char *)ER_CLIENT(CR_LOCALHOST_CONNECTION); ++} + #if defined(HAVE_SYS_UN_H) + if (!net->vio && + (!mysql->options.protocol || +diff --git a/sql/mysqld.cc b/sql/mysqld.cc +index 178a572a5aa..03b9d6346f9 100644 +--- a/sql/mysqld.cc ++++ b/sql/mysqld.cc +@@ -6353,7 +6353,9 @@ int mysqld_main(int argc, char **argv) + unireg_abort(MYSQLD_ABORT_EXIT); // Will do exit + } + ++#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + my_init_signals(); ++#endif + + size_t guardize = 0; + #ifndef _WIN32 +@@ -6837,8 +6839,10 @@ int mysqld_main(int argc, char **argv) + unireg_abort(MYSQLD_ABORT_EXIT); + + #ifndef _WIN32 ++#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + // Start signal handler thread. + start_signal_handler(); ++#endif + #endif + + /* set all persistent options */ +@@ -6980,8 +6984,9 @@ int mysqld_main(int argc, char **argv) + } + + start_handle_manager(); +- ++#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + create_compress_gtid_table_thread(); ++#endif + + LogEvent() + .type(LOG_TYPE_ERROR) +@@ -7028,6 +7033,10 @@ int mysqld_main(int argc, char **argv) + + (void)RUN_HOOK(server_state, before_handle_connection, (NULL)); + ++#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION ++ return 0; ++#endif ++ + #if defined(_WIN32) + setup_conn_event_handler_threads(); + #else +@@ -9850,6 +9859,9 @@ static int get_options(int *argc_ptr, char ***argv_ptr) { + + if (opt_short_log_format) opt_specialflag |= SPECIAL_SHORT_LOG_FORMAT; + ++#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION ++ Connection_handler_manager::thread_handling = Connection_handler_manager::SCHEDULER_NO_THREADS; ++#endif + if (Connection_handler_manager::init()) { + LogErr(ERROR_LEVEL, ER_CONNECTION_HANDLING_OOM); + return 1; +diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc +index 983603eb58c..d577c6fcc05 100644 +--- a/storage/innobase/buf/buf0buf.cc ++++ b/storage/innobase/buf/buf0buf.cc +@@ -1484,18 +1484,14 @@ dberr_t buf_pool_init(ulint total_size, ulint n_instances) { + n = n_instances; + } + +- std::vector threads; +- + std::mutex m; + + for (ulint id = i; id < n; ++id) { +- threads.emplace_back(std::thread(buf_pool_create, &buf_pool_ptr[id], size, +- id, &m, std::ref(errs[id]))); ++ buf_pool_create(&buf_pool_ptr[id], size, ++ id, &m, std::ref(errs[id])); + } + + for (ulint id = i; id < n; ++id) { +- threads[id - i].join(); +- + if (errs[id] != DB_SUCCESS) { + err = errs[id]; + } +diff --git a/vio/CMakeLists.txt b/vio/CMakeLists.txt +index 497ab98396c..a6cf2a647a6 100644 +--- a/vio/CMakeLists.txt ++++ b/vio/CMakeLists.txt +@@ -25,6 +25,7 @@ SET(VIO_SOURCES + viosocket.cc + viossl.cc + viosslfactories.cc ++ viofuzz.cc + ) + + IF(WIN32) +diff --git a/vio/vio.cc b/vio/vio.cc +index 85cc77df645..03ed154dcee 100644 +--- a/vio/vio.cc ++++ b/vio/vio.cc +@@ -300,6 +300,27 @@ static bool vio_init(Vio *vio, enum enum_vio_type type, my_socket sd, + return false; + } + #endif /* HAVE_OPENSSL */ ++ if (type == VIO_TYPE_FUZZ) { ++ vio->viodelete = vio_delete; ++ vio->vioerrno = vio_errno; ++ vio->read = vio_read_buff_fuzz; ++ vio->write = vio_write_buff_fuzz; ++ vio->fastsend = vio_fastsend_fuzz; ++ vio->viokeepalive = vio_keepalive_fuzz; ++ vio->should_retry = vio_should_retry_fuzz; ++ vio->was_timeout = vio_was_timeout_fuzz; ++ vio->vioshutdown = vio_shutdown_fuzz; ++ vio->peer_addr = vio_peer_addr; ++ vio->timeout = vio_socket_timeout_fuzz; ++ vio->io_wait = vio_io_wait_fuzz; ++ vio->is_connected = vio_is_connected_fuzz; ++ vio->has_data = vio->read_buffer ? vio_buff_has_data : has_no_data; ++ vio->is_blocking = vio_is_blocking; ++ vio->set_blocking = vio_set_blocking; ++ vio->set_blocking_flag = vio_set_blocking_flag; ++ vio->is_blocking_flag = false; ++ return false; ++ } + vio->viodelete = vio_delete; + vio->vioerrno = vio_errno; + vio->read = vio->read_buffer ? vio_read_buff : vio_read; +@@ -575,7 +596,8 @@ static const vio_string vio_type_names[] = {{"", 0}, + {STRING_WITH_LEN("SSL/TLS")}, + {STRING_WITH_LEN("Shared Memory")}, + {STRING_WITH_LEN("Internal")}, +- {STRING_WITH_LEN("Plugin")}}; ++ {STRING_WITH_LEN("Plugin")}, ++ {STRING_WITH_LEN("Fuzz")}}; + + void get_vio_type_name(enum enum_vio_type vio_type, const char **str, + int *len) { +diff --git a/vio/viofuzz.cc b/vio/viofuzz.cc +new file mode 100644 +index 00000000000..73f29662b96 +--- /dev/null ++++ b/vio/viofuzz.cc +@@ -0,0 +1,127 @@ ++ ++#include "my_config.h" ++ ++#include ++#include ++#include ++#include ++#ifndef _WIN32 ++#include ++#endif ++#include ++#include ++ ++#include "my_compiler.h" ++#include "my_dbug.h" ++#include "my_inttypes.h" ++#include "my_io.h" ++#include "my_macros.h" ++#include "vio/vio_priv.h" ++ ++#ifdef FIONREAD_IN_SYS_FILIO ++#include ++#endif ++#ifndef _WIN32 ++#include ++#endif ++#ifdef HAVE_POLL_H ++#include ++#endif ++#ifdef HAVE_SYS_IOCTL_H ++#include ++#endif ++ ++static const uint8_t *fuzzBuffer; ++static size_t fuzzSize; ++static size_t fuzzPos; ++ ++ ++void sock_initfuzz(const uint8_t *Data, size_t Size) { ++ fuzzPos = 0; ++ fuzzSize = Size; ++ fuzzBuffer = Data; ++} ++ ++bool vio_connect_fuzz(Vio *vio, struct sockaddr *addr, socklen_t len, ++ int timeout) { ++ int ret; ++ DBUG_ENTER("vio_socket_connect"); ++ ++ /* Only for socket-based transport types. */ ++ DBUG_ASSERT(vio->type == VIO_TYPE_SOCKET || vio->type == VIO_TYPE_TCPIP); ++ ++ /* Initiate the connection. */ ++ ret=0; ++ ++ DBUG_RETURN(MY_TEST(ret)); ++} ++ ++ ++int vio_socket_timeout_fuzz(Vio *vio, uint which, bool b) { ++ DBUG_ENTER("vio_socket_timeout_fuzz\n"); ++ return 0; ++} ++ ++ ++size_t vio_read_buff_fuzz(Vio *vio, uchar *bufp, size_t size) { ++ DBUG_ENTER("vio_read_buff_fuzz.\n"); ++ if (size > fuzzSize - fuzzPos) { ++ size = fuzzSize - fuzzPos; ++ } ++ if (fuzzPos < fuzzSize) { ++ memcpy(bufp, fuzzBuffer + fuzzPos, size); ++ } ++ fuzzPos += size; ++#ifdef FUZZ_DEBUG ++ printf("net cli %zu ", size); ++ for (size_t i=0; i +//#include +//#include +//#include +//#include +//#include +//#include +//#include +#include "sql/sql_class.h" +#include "sql/protocol_classic.h" +#include "sql/conn_handler/channel_info.h" +#include "sql/conn_handler/connection_handler.h" +#include "sql/conn_handler/connection_handler_manager.h" +#include "sql/conn_handler/init_net_server_extension.h" +#include "sql/conn_handler/connection_handler_impl.h" +#include "sql/mysqld.h" +#include "sql/set_var.h" +#include "sql/rpl_handler.h" +#include "sql/log.h" +#include "sql/opt_costconstantcache.h" +#include "sql/sql_plugin.h" +#include "sql/sql_thd_internal_api.h" +#include "sql/mysqld_thd_manager.h" +#include "sql/sql_parse.h" +#include "mysql/psi/mysql_socket.h" +#include "violite.h" +#include +#include + +using namespace std; +FILE *logfile = NULL; +Connection_handler_manager * chm; +extern int mysqld_main(int argc, char **argv); +char *filepath = NULL; + +extern "C" int LLVMFuzzerInitialize(const int* argc, char*** argv) { + filepath = dirname(strdup((*argv)[0])); + return 0; +} + + +const uint8_t startConn[] = +"\xa6\x00\x00\x01\x85\xa6\xff\x01\x00\x00\x00\x01\x2d\x00\x00\x00" \ +"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ +"\x00\x00\x00\x00\x72\x6f\x6f\x74\x00\x01\x00\x6d\x79\x73\x71\x6c" \ +"\x5f\x63\x6c\x65\x61\x72\x5f\x70\x61\x73\x73\x77\x6f\x72\x64\x00" \ +"\x69\x04\x5f\x70\x69\x64\x05\x35\x34\x30\x30\x31\x03\x5f\x6f\x73" \ +"\x08\x6f\x73\x78\x31\x30\x2e\x31\x33\x09\x5f\x70\x6c\x61\x74\x66" \ +"\x6f\x72\x6d\x06\x78\x38\x36\x5f\x36\x34\x0f\x5f\x63\x6c\x69\x65" \ +"\x6e\x74\x5f\x76\x65\x72\x73\x69\x6f\x6e\x06\x38\x2e\x30\x2e\x31" \ +"\x36\x0c\x5f\x63\x6c\x69\x65\x6e\x74\x5f\x6e\x61\x6d\x65\x08\x6c" \ +"\x69\x62\x6d\x79\x73\x71\x6c\x0c\x70\x72\x6f\x67\x72\x61\x6d\x5f" \ +"\x6e\x61\x6d\x65\x05\x6d\x79\x73\x71\x6c" +"\x00\x00\x00\x03" +; + + +class Channel_info_fuzz : public Channel_info { + bool m_is_admin_conn; + + protected: + virtual Vio *create_and_init_vio() const { + Vio *vio = vio_new(0, VIO_TYPE_FUZZ, VIO_LOCALHOST); + return vio; + } + + public: + Channel_info_fuzz(bool is_admin_conn) : m_is_admin_conn(is_admin_conn) {} + + virtual THD *create_thd() { + Vio *vio_tmp = create_and_init_vio(); + if (vio_tmp == NULL) return NULL; + + THD *thd = new (std::nothrow) THD(); + if (thd == NULL) { + vio_delete(vio_tmp); + return NULL; + } + thd->get_protocol_classic()->init_net(vio_tmp); + thd->set_admin_connection(m_is_admin_conn); + init_net_server_extension(thd); + return thd; + } + + virtual bool is_admin_connection() const { return m_is_admin_conn; } +}; + +#define MAX_SIZE 256 + + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 1) { + return 0; + } + if (logfile == NULL) { + my_progname = "fuzz_docommand"; + /* first init was run with + * mysqld --user=root --initialize-insecure --log-error-verbosity=5 --datadir=/out/mysql/data/ --basedir=/out/mysql/ + */ + system("rm -Rf /tmp/mysql"); + char command[MAX_SIZE]; + char argbase[MAX_SIZE]; + char arginitfile[MAX_SIZE]; + snprintf(command, MAX_SIZE-1, "cp -r %s/mysql/data /tmp/mysql", filepath); + //unsafe + system(command); + + snprintf(argbase, MAX_SIZE-1, "--basedir=%s/mysql/", filepath); + snprintf(arginitfile, MAX_SIZE-1, "--init-file=%s/initnopw.sql", filepath); + + char *fakeargv[] = {const_cast("fuzz_docommand"), + const_cast("--user=root"), + const_cast("--secure-file-priv=NULL"), + const_cast("--log-error-verbosity=5"), + const_cast("--explicit_defaults_for_timestamp"), + //we should adapt vio_fuzz to give a socket to openssl in order to support ssl + const_cast("--skip-ssl"), + const_cast("--mysqlx=0"), + const_cast("--event-scheduler=DISABLED"), + const_cast("--performance_schema=OFF"), + const_cast("--thread_stack=1048576"), + const_cast("--datadir=/tmp/mysql/"), + const_cast("--port=3301"), + const_cast("--socket=/tmp/docommand.sock"), + const_cast(argbase), + const_cast(arginitfile), + 0}; + int fakeargc = 15; + mysqld_main(fakeargc, fakeargv); + + chm = Connection_handler_manager::get_instance(); + logfile = fopen("/dev/null", "w"); + } + Channel_info_fuzz * channel_info = new (std::nothrow) Channel_info_fuzz(true); + sock_initfuzz(startConn,sizeof(startConn)); + if (my_thread_init()) { + channel_info->send_error_and_close_channel(ER_OUT_OF_RESOURCES, 0, false); + abort(); + } + + THD *thd_fuzz = channel_info->create_thd(); + if (thd_fuzz == NULL) { + channel_info->send_error_and_close_channel(ER_OUT_OF_RESOURCES, 0, false); + abort(); + } + + thd_fuzz->set_new_thread_id(); + thd_set_thread_stack(thd_fuzz, (char *)&thd_fuzz); + thd_fuzz->store_globals(); + mysql_thread_set_psi_id(thd_fuzz->thread_id()); + mysql_socket_set_thread_owner( + thd_fuzz->get_protocol_classic()->get_vio()->mysql_socket); + Global_THD_manager *thd_manager = Global_THD_manager::get_instance(); + thd_manager->add_thd(thd_fuzz); + if (thd_prepare_connection(thd_fuzz)) { + abort(); + } + delete channel_info; + + // The fuzzing takes place on network data received from client + sock_initfuzz(Data,Size); + + while (thd_connection_alive(thd_fuzz)) { + if (do_command(thd_fuzz)) break; + } + end_connection(thd_fuzz); + close_connection(thd_fuzz, 0, false, false); + thd_fuzz->release_resources(); + thd_manager->remove_thd(thd_fuzz); + delete thd_fuzz; + + return 0; +} diff --git a/projects/mysql-server/targets/fuzz_docommand.dict b/projects/mysql-server/targets/fuzz_docommand.dict new file mode 100644 index 000000000..b53c5dfa6 --- /dev/null +++ b/projects/mysql-server/targets/fuzz_docommand.dict @@ -0,0 +1,688 @@ +#SELECT WORD FROM INFORMATION_SCHEMA.KEYWORDS; +ACCESSIBLE +ACCOUNT +ACTION +ACTIVE +ADD +ADMIN +AFTER +AGAINST +AGGREGATE +ALGORITHM +ALL +ALTER +ALWAYS +ANALYZE +AND +ANY +AS +ASC +ASCII +ASENSITIVE +AT +AUTOEXTEND_SIZE +AUTO_INCREMENT +AVG +AVG_ROW_LENGTH +BACKUP +BEFORE +BEGIN +BETWEEN +BIGINT +BINARY +BINLOG +BIT +BLOB +BLOCK +BOOL +BOOLEAN +BOTH +BTREE +BUCKETS +BY +BYTE +CACHE +CALL +CASCADE +CASCADED +CASE +CATALOG_NAME +CHAIN +CHANGE +CHANGED +CHANNEL +CHAR +CHARACTER +CHARSET +CHECK +CHECKSUM +CIPHER +CLASS_ORIGIN +CLIENT +CLONE +CLOSE +COALESCE +CODE +COLLATE +COLLATION +COLUMN +COLUMNS +COLUMN_FORMAT +COLUMN_NAME +COMMENT +COMMIT +COMMITTED +COMPACT +COMPLETION +COMPONENT +COMPRESSED +COMPRESSION +CONCURRENT +CONDITION +CONNECTION +CONSISTENT +CONSTRAINT +CONSTRAINT_CATALOG +CONSTRAINT_NAME +CONSTRAINT_SCHEMA +CONTAINS +CONTEXT +CONTINUE +CONVERT +CPU +CREATE +CROSS +CUBE +CUME_DIST +CURRENT +CURRENT_DATE +CURRENT_TIME +CURRENT_TIMESTAMP +CURRENT_USER +CURSOR +CURSOR_NAME +DATA +DATABASE +DATABASES +DATAFILE +DATE +DATETIME +DAY +DAY_HOUR +DAY_MICROSECOND +DAY_MINUTE +DAY_SECOND +DEALLOCATE +DEC +DECIMAL +DECLARE +DEFAULT +DEFAULT_AUTH +DEFINER +DEFINITION +DELAYED +DELAY_KEY_WRITE +DELETE +DENSE_RANK +DESC +DESCRIBE +DESCRIPTION +DETERMINISTIC +DIAGNOSTICS +DIRECTORY +DISABLE +DISCARD +DISK +DISTINCT +DISTINCTROW +DIV +DO +DOUBLE +DROP +DUAL +DUMPFILE +DUPLICATE +DYNAMIC +EACH +ELSE +ELSEIF +EMPTY +ENABLE +ENCLOSED +ENCRYPTION +END +ENDS +ENFORCED +ENGINE +ENGINES +ENUM +ERROR +ERRORS +ESCAPE +ESCAPED +EVENT +EVENTS +EVERY +EXCEPT +EXCHANGE +EXCLUDE +EXECUTE +EXISTS +EXIT +EXPANSION +EXPIRE +EXPLAIN +EXPORT +EXTENDED +EXTENT_SIZE +FALSE +FAST +FAULTS +FETCH +FIELDS +FILE +FILE_BLOCK_SIZE +FILTER +FIRST +FIRST_VALUE +FIXED +FLOAT +FLOAT4 +FLOAT8 +FLUSH +FOLLOWING +FOLLOWS +FOR +FORCE +FOREIGN +FORMAT +FOUND +FROM +FULL +FULLTEXT +FUNCTION +GENERAL +GENERATED +GEOMCOLLECTION +GEOMETRY +GEOMETRYCOLLECTION +GET +GET_FORMAT +GET_MASTER_PUBLIC_KEY +GLOBAL +GRANT +GRANTS +GROUP +GROUPING +GROUPS +GROUP_REPLICATION +HANDLER +HASH +HAVING +HELP +HIGH_PRIORITY +HISTOGRAM +HISTORY +HOST +HOSTS +HOUR +HOUR_MICROSECOND +HOUR_MINUTE +HOUR_SECOND +IDENTIFIED +IF +IGNORE +IGNORE_SERVER_IDS +IMPORT +IN +INACTIVE +INDEX +INDEXES +INFILE +INITIAL_SIZE +INNER +INOUT +INSENSITIVE +INSERT +INSERT_METHOD +INSTALL +INSTANCE +INT +INT1 +INT2 +INT3 +INT4 +INT8 +INTEGER +INTERVAL +INTO +INVISIBLE +INVOKER +IO +IO_AFTER_GTIDS +IO_BEFORE_GTIDS +IO_THREAD +IPC +IS +ISOLATION +ISSUER +ITERATE +JOIN +JSON +JSON_TABLE +KEY +KEYS +KEY_BLOCK_SIZE +KILL +LAG +LANGUAGE +LAST +LAST_VALUE +LATERAL +LEAD +LEADING +LEAVE +LEAVES +LEFT +LESS +LEVEL +LIKE +LIMIT +LINEAR +LINES +LINESTRING +LIST +LOAD +LOCAL +LOCALTIME +LOCALTIMESTAMP +LOCK +LOCKED +LOCKS +LOGFILE +LOGS +LONG +LONGBLOB +LONGTEXT +LOOP +LOW_PRIORITY +MASTER +MASTER_AUTO_POSITION +MASTER_BIND +MASTER_CONNECT_RETRY +MASTER_DELAY +MASTER_HEARTBEAT_PERIOD +MASTER_HOST +MASTER_LOG_FILE +MASTER_LOG_POS +MASTER_PASSWORD +MASTER_PORT +MASTER_PUBLIC_KEY_PATH +MASTER_RETRY_COUNT +MASTER_SERVER_ID +MASTER_SSL +MASTER_SSL_CA +MASTER_SSL_CAPATH +MASTER_SSL_CERT +MASTER_SSL_CIPHER +MASTER_SSL_CRL +MASTER_SSL_CRLPATH +MASTER_SSL_KEY +MASTER_SSL_VERIFY_SERVER_CERT +MASTER_TLS_VERSION +MASTER_USER +MATCH +MAXVALUE +MAX_CONNECTIONS_PER_HOUR +MAX_QUERIES_PER_HOUR +MAX_ROWS +MAX_SIZE +MAX_UPDATES_PER_HOUR +MAX_USER_CONNECTIONS +MEDIUM +MEDIUMBLOB +MEDIUMINT +MEDIUMTEXT +MEMORY +MERGE +MESSAGE_TEXT +MICROSECOND +MIDDLEINT +MIGRATE +MINUTE +MINUTE_MICROSECOND +MINUTE_SECOND +MIN_ROWS +MOD +MODE +MODIFIES +MODIFY +MONTH +MULTILINESTRING +MULTIPOINT +MULTIPOLYGON +MUTEX +MYSQL_ERRNO +NAME +NAMES +NATIONAL +NATURAL +NCHAR +NDB +NDBCLUSTER +NESTED +NETWORK_NAMESPACE +NEVER +NEW +NEXT +NO +NODEGROUP +NONE +NOT +NOWAIT +NO_WAIT +NO_WRITE_TO_BINLOG +NTH_VALUE +NTILE +NULL +NULLS +NUMBER +NUMERIC +NVARCHAR +OF +OFFSET +OJ +OLD +ON +ONE +ONLY +OPEN +OPTIMIZE +OPTIMIZER_COSTS +OPTION +OPTIONAL +OPTIONALLY +OPTIONS +OR +ORDER +ORDINALITY +ORGANIZATION +OTHERS +OUT +OUTER +OUTFILE +OVER +OWNER +PACK_KEYS +PAGE +PARSER +PARTIAL +PARTITION +PARTITIONING +PARTITIONS +PASSWORD +PATH +PERCENT_RANK +PERSIST +PERSIST_ONLY +PHASE +PLUGIN +PLUGINS +PLUGIN_DIR +POINT +POLYGON +PORT +PRECEDES +PRECEDING +PRECISION +PREPARE +PRESERVE +PREV +PRIMARY +PRIVILEGES +PROCEDURE +PROCESS +PROCESSLIST +PROFILE +PROFILES +PROXY +PURGE +QUARTER +QUERY +QUICK +RANGE +RANK +READ +READS +READ_ONLY +READ_WRITE +REAL +REBUILD +RECOVER +RECURSIVE +REDO_BUFFER_SIZE +REDUNDANT +REFERENCE +REFERENCES +REGEXP +RELAY +RELAYLOG +RELAY_LOG_FILE +RELAY_LOG_POS +RELAY_THREAD +RELEASE +RELOAD +REMOVE +RENAME +REORGANIZE +REPAIR +REPEAT +REPEATABLE +REPLACE +REPLICATE_DO_DB +REPLICATE_DO_TABLE +REPLICATE_IGNORE_DB +REPLICATE_IGNORE_TABLE +REPLICATE_REWRITE_DB +REPLICATE_WILD_DO_TABLE +REPLICATE_WILD_IGNORE_TABLE +REPLICATION +REQUIRE +RESET +RESIGNAL +RESOURCE +RESPECT +RESTART +RESTORE +RESTRICT +RESUME +RETAIN +RETURN +RETURNED_SQLSTATE +RETURNS +REUSE +REVERSE +REVOKE +RIGHT +RLIKE +ROLE +ROLLBACK +ROLLUP +ROTATE +ROUTINE +ROW +ROWS +ROW_COUNT +ROW_FORMAT +ROW_NUMBER +RTREE +SAVEPOINT +SCHEDULE +SCHEMA +SCHEMAS +SCHEMA_NAME +SECOND +SECONDARY +SECONDARY_ENGINE +SECONDARY_LOAD +SECONDARY_UNLOAD +SECOND_MICROSECOND +SECURITY +SELECT +SENSITIVE +SEPARATOR +SERIAL +SERIALIZABLE +SERVER +SESSION +SET +SHARE +SHOW +SHUTDOWN +SIGNAL +SIGNED +SIMPLE +SKIP +SLAVE +SLOW +SMALLINT +SNAPSHOT +SOCKET +SOME +SONAME +SOUNDS +SOURCE +SPATIAL +SPECIFIC +SQL +SQLEXCEPTION +SQLSTATE +SQLWARNING +SQL_AFTER_GTIDS +SQL_AFTER_MTS_GAPS +SQL_BEFORE_GTIDS +SQL_BIG_RESULT +SQL_BUFFER_RESULT +SQL_CALC_FOUND_ROWS +SQL_NO_CACHE +SQL_SMALL_RESULT +SQL_THREAD +SQL_TSI_DAY +SQL_TSI_HOUR +SQL_TSI_MINUTE +SQL_TSI_MONTH +SQL_TSI_QUARTER +SQL_TSI_SECOND +SQL_TSI_WEEK +SQL_TSI_YEAR +SRID +SSL +STACKED +START +STARTING +STARTS +STATS_AUTO_RECALC +STATS_PERSISTENT +STATS_SAMPLE_PAGES +STATUS +STOP +STORAGE +STORED +STRAIGHT_JOIN +STRING +SUBCLASS_ORIGIN +SUBJECT +SUBPARTITION +SUBPARTITIONS +SUPER +SUSPEND +SWAPS +SWITCHES +SYSTEM +TABLE +TABLES +TABLESPACE +TABLE_CHECKSUM +TABLE_NAME +TEMPORARY +TEMPTABLE +TERMINATED +TEXT +THAN +THEN +THREAD_PRIORITY +TIES +TIME +TIMESTAMP +TIMESTAMPADD +TIMESTAMPDIFF +TINYBLOB +TINYINT +TINYTEXT +TO +TRAILING +TRANSACTION +TRIGGER +TRIGGERS +TRUE +TRUNCATE +TYPE +TYPES +UNBOUNDED +UNCOMMITTED +UNDEFINED +UNDO +UNDOFILE +UNDO_BUFFER_SIZE +UNICODE +UNINSTALL +UNION +UNIQUE +UNKNOWN +UNLOCK +UNSIGNED +UNTIL +UPDATE +UPGRADE +USAGE +USE +USER +USER_RESOURCES +USE_FRM +USING +UTC_DATE +UTC_TIME +UTC_TIMESTAMP +VALIDATION +VALUE +VALUES +VARBINARY +VARCHAR +VARCHARACTER +VARIABLES +VARYING +VCPU +VIEW +VIRTUAL +VISIBLE +WAIT +WARNINGS +WEEK +WEIGHT_STRING +WHEN +WHERE +WHILE +WINDOW +WITH +WITHOUT +WORK +WRAPPER +WRITE +X509 +XA +XID +XML +XOR +YEAR +YEAR_MONTH +ZEROFILL diff --git a/projects/mysql-server/targets/fuzz_docommand.options b/projects/mysql-server/targets/fuzz_docommand.options new file mode 100644 index 000000000..329a6e27b --- /dev/null +++ b/projects/mysql-server/targets/fuzz_docommand.options @@ -0,0 +1,2 @@ +[libfuzzer] +close_fd_mask = 3 diff --git a/projects/mysql-server/targets/fuzz_initfile.cc b/projects/mysql-server/targets/fuzz_initfile.cc new file mode 100644 index 000000000..5fcef60f4 --- /dev/null +++ b/projects/mysql-server/targets/fuzz_initfile.cc @@ -0,0 +1,117 @@ +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +#include "sql/sql_class.h" +#include "sql/conn_handler/channel_info.h" +#include "sql/conn_handler/connection_handler.h" +#include "sql/conn_handler/connection_handler_manager.h" +#include "sql/conn_handler/init_net_server_extension.h" +#include "sql/conn_handler/connection_handler_impl.h" +#include "sql/mysqld.h" +#include "sql/set_var.h" +#include "sql/rpl_handler.h" +#include "sql/log.h" +#include "sql/opt_costconstantcache.h" +#include "sql/sql_plugin.h" +#include "sql/sql_thd_internal_api.h" +#include "sql/mysqld_thd_manager.h" +#include "sql/bootstrap.h" +#include "mysql/psi/mysql_socket.h" +#include "mysql/psi/mysql_file.h" +#include "violite.h" +#include +#include + +using namespace std; +FILE *logfile = NULL; +extern int mysqld_main(int argc, char **argv); +char *filepath = NULL; + +extern "C" int LLVMFuzzerInitialize(const int* argc, char*** argv) { + filepath = dirname(strdup((*argv)[0])); + return 0; +} + +static int bufferToFile(const char * name, const uint8_t *Data, size_t Size) { + FILE * fd; + if (remove(name) != 0) { + if (errno != ENOENT) { + printf("failed remove, errno=%d\n", errno); + return -1; + } + } + fd = fopen(name, "wb"); + if (fd == NULL) { + printf("failed open, errno=%d\n", errno); + return -2; + } + if (fwrite (Data, 1, Size, fd) != Size) { + fclose(fd); + return -3; + } + fclose(fd); + return 0; +} + +#define MAX_SIZE 256 + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 1) { + return 0; + } + if (logfile == NULL) { + my_progname = "fuzz_initfile"; + /* first init was run with + * mysqld --user=root --initialize-insecure --log-error-verbosity=5 --datadir=/out/mysql/data/ --basedir=/out/mysql/ + */ + system("rm -Rf /tmp/mysql"); + char command[MAX_SIZE]; + char argbase[MAX_SIZE]; + char arginitfile[MAX_SIZE]; + snprintf(command, MAX_SIZE-1, "cp -r %s/mysql/data /tmp/mysql", filepath); + //unsafe + system(command); + + snprintf(argbase, MAX_SIZE-1, "--basedir=%s/mysql/", filepath); + snprintf(arginitfile, MAX_SIZE-1, "--init-file=%s/initnopw.sql", filepath); + + char *fakeargv[] = {const_cast("fuzz_initfile"), + const_cast("--user=root"), + const_cast("--secure-file-priv=NULL"), + const_cast("--log-error-verbosity=5"), + const_cast("--explicit_defaults_for_timestamp"), + //we should adapt vio_fuzz to give a socket to openssl in order to support ssl + const_cast("--skip-ssl"), + const_cast("--mysqlx=0"), + const_cast("--event-scheduler=DISABLED"), + const_cast("--performance_schema=OFF"), + const_cast("--thread_stack=1048576"), + const_cast("--datadir=/tmp/mysql/"), + const_cast("--port=3302"), + const_cast("--socket=/tmp/initfile.sock"), + const_cast(argbase), + const_cast(arginitfile), + 0}; + int fakeargc = 15; + mysqld_main(fakeargc, fakeargv); + //terminate_compress_gtid_table_thread(); + + logfile = fopen("/dev/null", "w"); + } + + bufferToFile("/tmp/initfuzz.sql", Data, Size); + MYSQL_FILE *file; + if (!(file = + mysql_file_fopen(key_file_init, "/tmp/initfuzz.sql", O_RDONLY, MYF(MY_WME)))) { + abort(); + } + (void)bootstrap::run_bootstrap_thread("/tmp/initfuzz.sql", file, NULL, SYSTEM_THREAD_INIT_FILE); + mysql_file_fclose(file, MYF(MY_WME)); + + return 0; +} diff --git a/projects/mysql-server/targets/fuzz_initfile.dict b/projects/mysql-server/targets/fuzz_initfile.dict new file mode 100644 index 000000000..b53c5dfa6 --- /dev/null +++ b/projects/mysql-server/targets/fuzz_initfile.dict @@ -0,0 +1,688 @@ +#SELECT WORD FROM INFORMATION_SCHEMA.KEYWORDS; +ACCESSIBLE +ACCOUNT +ACTION +ACTIVE +ADD +ADMIN +AFTER +AGAINST +AGGREGATE +ALGORITHM +ALL +ALTER +ALWAYS +ANALYZE +AND +ANY +AS +ASC +ASCII +ASENSITIVE +AT +AUTOEXTEND_SIZE +AUTO_INCREMENT +AVG +AVG_ROW_LENGTH +BACKUP +BEFORE +BEGIN +BETWEEN +BIGINT +BINARY +BINLOG +BIT +BLOB +BLOCK +BOOL +BOOLEAN +BOTH +BTREE +BUCKETS +BY +BYTE +CACHE +CALL +CASCADE +CASCADED +CASE +CATALOG_NAME +CHAIN +CHANGE +CHANGED +CHANNEL +CHAR +CHARACTER +CHARSET +CHECK +CHECKSUM +CIPHER +CLASS_ORIGIN +CLIENT +CLONE +CLOSE +COALESCE +CODE +COLLATE +COLLATION +COLUMN +COLUMNS +COLUMN_FORMAT +COLUMN_NAME +COMMENT +COMMIT +COMMITTED +COMPACT +COMPLETION +COMPONENT +COMPRESSED +COMPRESSION +CONCURRENT +CONDITION +CONNECTION +CONSISTENT +CONSTRAINT +CONSTRAINT_CATALOG +CONSTRAINT_NAME +CONSTRAINT_SCHEMA +CONTAINS +CONTEXT +CONTINUE +CONVERT +CPU +CREATE +CROSS +CUBE +CUME_DIST +CURRENT +CURRENT_DATE +CURRENT_TIME +CURRENT_TIMESTAMP +CURRENT_USER +CURSOR +CURSOR_NAME +DATA +DATABASE +DATABASES +DATAFILE +DATE +DATETIME +DAY +DAY_HOUR +DAY_MICROSECOND +DAY_MINUTE +DAY_SECOND +DEALLOCATE +DEC +DECIMAL +DECLARE +DEFAULT +DEFAULT_AUTH +DEFINER +DEFINITION +DELAYED +DELAY_KEY_WRITE +DELETE +DENSE_RANK +DESC +DESCRIBE +DESCRIPTION +DETERMINISTIC +DIAGNOSTICS +DIRECTORY +DISABLE +DISCARD +DISK +DISTINCT +DISTINCTROW +DIV +DO +DOUBLE +DROP +DUAL +DUMPFILE +DUPLICATE +DYNAMIC +EACH +ELSE +ELSEIF +EMPTY +ENABLE +ENCLOSED +ENCRYPTION +END +ENDS +ENFORCED +ENGINE +ENGINES +ENUM +ERROR +ERRORS +ESCAPE +ESCAPED +EVENT +EVENTS +EVERY +EXCEPT +EXCHANGE +EXCLUDE +EXECUTE +EXISTS +EXIT +EXPANSION +EXPIRE +EXPLAIN +EXPORT +EXTENDED +EXTENT_SIZE +FALSE +FAST +FAULTS +FETCH +FIELDS +FILE +FILE_BLOCK_SIZE +FILTER +FIRST +FIRST_VALUE +FIXED +FLOAT +FLOAT4 +FLOAT8 +FLUSH +FOLLOWING +FOLLOWS +FOR +FORCE +FOREIGN +FORMAT +FOUND +FROM +FULL +FULLTEXT +FUNCTION +GENERAL +GENERATED +GEOMCOLLECTION +GEOMETRY +GEOMETRYCOLLECTION +GET +GET_FORMAT +GET_MASTER_PUBLIC_KEY +GLOBAL +GRANT +GRANTS +GROUP +GROUPING +GROUPS +GROUP_REPLICATION +HANDLER +HASH +HAVING +HELP +HIGH_PRIORITY +HISTOGRAM +HISTORY +HOST +HOSTS +HOUR +HOUR_MICROSECOND +HOUR_MINUTE +HOUR_SECOND +IDENTIFIED +IF +IGNORE +IGNORE_SERVER_IDS +IMPORT +IN +INACTIVE +INDEX +INDEXES +INFILE +INITIAL_SIZE +INNER +INOUT +INSENSITIVE +INSERT +INSERT_METHOD +INSTALL +INSTANCE +INT +INT1 +INT2 +INT3 +INT4 +INT8 +INTEGER +INTERVAL +INTO +INVISIBLE +INVOKER +IO +IO_AFTER_GTIDS +IO_BEFORE_GTIDS +IO_THREAD +IPC +IS +ISOLATION +ISSUER +ITERATE +JOIN +JSON +JSON_TABLE +KEY +KEYS +KEY_BLOCK_SIZE +KILL +LAG +LANGUAGE +LAST +LAST_VALUE +LATERAL +LEAD +LEADING +LEAVE +LEAVES +LEFT +LESS +LEVEL +LIKE +LIMIT +LINEAR +LINES +LINESTRING +LIST +LOAD +LOCAL +LOCALTIME +LOCALTIMESTAMP +LOCK +LOCKED +LOCKS +LOGFILE +LOGS +LONG +LONGBLOB +LONGTEXT +LOOP +LOW_PRIORITY +MASTER +MASTER_AUTO_POSITION +MASTER_BIND +MASTER_CONNECT_RETRY +MASTER_DELAY +MASTER_HEARTBEAT_PERIOD +MASTER_HOST +MASTER_LOG_FILE +MASTER_LOG_POS +MASTER_PASSWORD +MASTER_PORT +MASTER_PUBLIC_KEY_PATH +MASTER_RETRY_COUNT +MASTER_SERVER_ID +MASTER_SSL +MASTER_SSL_CA +MASTER_SSL_CAPATH +MASTER_SSL_CERT +MASTER_SSL_CIPHER +MASTER_SSL_CRL +MASTER_SSL_CRLPATH +MASTER_SSL_KEY +MASTER_SSL_VERIFY_SERVER_CERT +MASTER_TLS_VERSION +MASTER_USER +MATCH +MAXVALUE +MAX_CONNECTIONS_PER_HOUR +MAX_QUERIES_PER_HOUR +MAX_ROWS +MAX_SIZE +MAX_UPDATES_PER_HOUR +MAX_USER_CONNECTIONS +MEDIUM +MEDIUMBLOB +MEDIUMINT +MEDIUMTEXT +MEMORY +MERGE +MESSAGE_TEXT +MICROSECOND +MIDDLEINT +MIGRATE +MINUTE +MINUTE_MICROSECOND +MINUTE_SECOND +MIN_ROWS +MOD +MODE +MODIFIES +MODIFY +MONTH +MULTILINESTRING +MULTIPOINT +MULTIPOLYGON +MUTEX +MYSQL_ERRNO +NAME +NAMES +NATIONAL +NATURAL +NCHAR +NDB +NDBCLUSTER +NESTED +NETWORK_NAMESPACE +NEVER +NEW +NEXT +NO +NODEGROUP +NONE +NOT +NOWAIT +NO_WAIT +NO_WRITE_TO_BINLOG +NTH_VALUE +NTILE +NULL +NULLS +NUMBER +NUMERIC +NVARCHAR +OF +OFFSET +OJ +OLD +ON +ONE +ONLY +OPEN +OPTIMIZE +OPTIMIZER_COSTS +OPTION +OPTIONAL +OPTIONALLY +OPTIONS +OR +ORDER +ORDINALITY +ORGANIZATION +OTHERS +OUT +OUTER +OUTFILE +OVER +OWNER +PACK_KEYS +PAGE +PARSER +PARTIAL +PARTITION +PARTITIONING +PARTITIONS +PASSWORD +PATH +PERCENT_RANK +PERSIST +PERSIST_ONLY +PHASE +PLUGIN +PLUGINS +PLUGIN_DIR +POINT +POLYGON +PORT +PRECEDES +PRECEDING +PRECISION +PREPARE +PRESERVE +PREV +PRIMARY +PRIVILEGES +PROCEDURE +PROCESS +PROCESSLIST +PROFILE +PROFILES +PROXY +PURGE +QUARTER +QUERY +QUICK +RANGE +RANK +READ +READS +READ_ONLY +READ_WRITE +REAL +REBUILD +RECOVER +RECURSIVE +REDO_BUFFER_SIZE +REDUNDANT +REFERENCE +REFERENCES +REGEXP +RELAY +RELAYLOG +RELAY_LOG_FILE +RELAY_LOG_POS +RELAY_THREAD +RELEASE +RELOAD +REMOVE +RENAME +REORGANIZE +REPAIR +REPEAT +REPEATABLE +REPLACE +REPLICATE_DO_DB +REPLICATE_DO_TABLE +REPLICATE_IGNORE_DB +REPLICATE_IGNORE_TABLE +REPLICATE_REWRITE_DB +REPLICATE_WILD_DO_TABLE +REPLICATE_WILD_IGNORE_TABLE +REPLICATION +REQUIRE +RESET +RESIGNAL +RESOURCE +RESPECT +RESTART +RESTORE +RESTRICT +RESUME +RETAIN +RETURN +RETURNED_SQLSTATE +RETURNS +REUSE +REVERSE +REVOKE +RIGHT +RLIKE +ROLE +ROLLBACK +ROLLUP +ROTATE +ROUTINE +ROW +ROWS +ROW_COUNT +ROW_FORMAT +ROW_NUMBER +RTREE +SAVEPOINT +SCHEDULE +SCHEMA +SCHEMAS +SCHEMA_NAME +SECOND +SECONDARY +SECONDARY_ENGINE +SECONDARY_LOAD +SECONDARY_UNLOAD +SECOND_MICROSECOND +SECURITY +SELECT +SENSITIVE +SEPARATOR +SERIAL +SERIALIZABLE +SERVER +SESSION +SET +SHARE +SHOW +SHUTDOWN +SIGNAL +SIGNED +SIMPLE +SKIP +SLAVE +SLOW +SMALLINT +SNAPSHOT +SOCKET +SOME +SONAME +SOUNDS +SOURCE +SPATIAL +SPECIFIC +SQL +SQLEXCEPTION +SQLSTATE +SQLWARNING +SQL_AFTER_GTIDS +SQL_AFTER_MTS_GAPS +SQL_BEFORE_GTIDS +SQL_BIG_RESULT +SQL_BUFFER_RESULT +SQL_CALC_FOUND_ROWS +SQL_NO_CACHE +SQL_SMALL_RESULT +SQL_THREAD +SQL_TSI_DAY +SQL_TSI_HOUR +SQL_TSI_MINUTE +SQL_TSI_MONTH +SQL_TSI_QUARTER +SQL_TSI_SECOND +SQL_TSI_WEEK +SQL_TSI_YEAR +SRID +SSL +STACKED +START +STARTING +STARTS +STATS_AUTO_RECALC +STATS_PERSISTENT +STATS_SAMPLE_PAGES +STATUS +STOP +STORAGE +STORED +STRAIGHT_JOIN +STRING +SUBCLASS_ORIGIN +SUBJECT +SUBPARTITION +SUBPARTITIONS +SUPER +SUSPEND +SWAPS +SWITCHES +SYSTEM +TABLE +TABLES +TABLESPACE +TABLE_CHECKSUM +TABLE_NAME +TEMPORARY +TEMPTABLE +TERMINATED +TEXT +THAN +THEN +THREAD_PRIORITY +TIES +TIME +TIMESTAMP +TIMESTAMPADD +TIMESTAMPDIFF +TINYBLOB +TINYINT +TINYTEXT +TO +TRAILING +TRANSACTION +TRIGGER +TRIGGERS +TRUE +TRUNCATE +TYPE +TYPES +UNBOUNDED +UNCOMMITTED +UNDEFINED +UNDO +UNDOFILE +UNDO_BUFFER_SIZE +UNICODE +UNINSTALL +UNION +UNIQUE +UNKNOWN +UNLOCK +UNSIGNED +UNTIL +UPDATE +UPGRADE +USAGE +USE +USER +USER_RESOURCES +USE_FRM +USING +UTC_DATE +UTC_TIME +UTC_TIMESTAMP +VALIDATION +VALUE +VALUES +VARBINARY +VARCHAR +VARCHARACTER +VARIABLES +VARYING +VCPU +VIEW +VIRTUAL +VISIBLE +WAIT +WARNINGS +WEEK +WEIGHT_STRING +WHEN +WHERE +WHILE +WINDOW +WITH +WITHOUT +WORK +WRAPPER +WRITE +X509 +XA +XID +XML +XOR +YEAR +YEAR_MONTH +ZEROFILL diff --git a/projects/mysql-server/targets/fuzz_initfile.options b/projects/mysql-server/targets/fuzz_initfile.options new file mode 100644 index 000000000..7ca5e76f5 --- /dev/null +++ b/projects/mysql-server/targets/fuzz_initfile.options @@ -0,0 +1,2 @@ +[libfuzzer] +close_fd_mask = 2 diff --git a/projects/mysql-server/targets/fuzz_mysqld.cc b/projects/mysql-server/targets/fuzz_mysqld.cc new file mode 100644 index 000000000..05f3dbe8c --- /dev/null +++ b/projects/mysql-server/targets/fuzz_mysqld.cc @@ -0,0 +1,164 @@ +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +#include "sql/sql_class.h" +#include "sql/protocol_classic.h" +#include "sql/conn_handler/channel_info.h" +#include "sql/conn_handler/connection_handler.h" +#include "sql/conn_handler/connection_handler_manager.h" +#include "sql/conn_handler/init_net_server_extension.h" +#include "sql/conn_handler/connection_handler_impl.h" +#include "sql/mysqld.h" +#include "sql/set_var.h" +#include "sql/rpl_handler.h" +#include "sql/log.h" +#include "sql/opt_costconstantcache.h" +#include "sql/sql_plugin.h" +#include "sql/sql_thd_internal_api.h" +#include "sql/mysqld_thd_manager.h" +#include "mysql/psi/mysql_socket.h" +#include "violite.h" +#include +#include + +using namespace std; +FILE *logfile = NULL; +extern int mysqld_main(int argc, char **argv); +char *filepath = NULL; + +extern "C" int LLVMFuzzerInitialize(const int* argc, char*** argv) { + filepath = dirname(strdup((*argv)[0])); + return 0; +} + +class Channel_info_fuzz : public Channel_info { + bool m_is_admin_conn; + + protected: + virtual Vio *create_and_init_vio() const { + Vio *vio = vio_new(0, VIO_TYPE_FUZZ, VIO_LOCALHOST); + return vio; + } + + public: + Channel_info_fuzz(bool is_admin_conn) : m_is_admin_conn(is_admin_conn) {} + + virtual THD *create_thd() { + Vio *vio_tmp = create_and_init_vio(); + if (vio_tmp == NULL) return NULL; + + THD *thd = new (std::nothrow) THD(); + if (thd == NULL) { + vio_delete(vio_tmp); + return NULL; + } + thd->get_protocol_classic()->init_net(vio_tmp); + thd->set_admin_connection(m_is_admin_conn); + init_net_server_extension(thd); + return thd; + } + + virtual bool is_admin_connection() const { return m_is_admin_conn; } +}; + +static void try_connection(Channel_info *channel_info) { + if (my_thread_init()) { + channel_info->send_error_and_close_channel(ER_OUT_OF_RESOURCES, 0, false); + return; + } + + THD *thd = channel_info->create_thd(); + if (thd == NULL) { + channel_info->send_error_and_close_channel(ER_OUT_OF_RESOURCES, 0, false); + return; + } + + thd->set_new_thread_id(); + + /* + handle_one_connection() is normally the only way a thread would + start and would always be on the very high end of the stack , + therefore, the thread stack always starts at the address of the + first local variable of handle_one_connection, which is thd. We + need to know the start of the stack so that we could check for + stack overruns. + */ + thd_set_thread_stack(thd, (char *)&thd); + thd->store_globals(); + + mysql_thread_set_psi_id(thd->thread_id()); + mysql_socket_set_thread_owner( + thd->get_protocol_classic()->get_vio()->mysql_socket); + + Global_THD_manager *thd_manager = Global_THD_manager::get_instance(); + thd_manager->add_thd(thd); + + if (!thd_prepare_connection(thd)) { + //authentication bypass + abort(); + } + delete channel_info; + close_connection(thd, 0, false, false); + thd->release_resources(); + thd_manager->remove_thd(thd); + delete thd; +} + + +#define MAX_SIZE 256 + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (Size < 1) { + return 0; + } + if (logfile == NULL) { + my_progname = "fuzz_mysqld"; + /* first init was run with + * mysqld --user=root --initialize-insecure --log-error-verbosity=5 --datadir=/out/mysql/data/ --basedir=/out/mysql/ + */ + system("rm -Rf /tmp/mysql"); + char command[MAX_SIZE]; + char argbase[MAX_SIZE]; + char arginitfile[MAX_SIZE]; + snprintf(command, MAX_SIZE-1, "cp -r %s/mysql/data /tmp/mysql", filepath); + //unsafe + system(command); + + snprintf(argbase, MAX_SIZE-1, "--basedir=%s/mysql/", filepath); + snprintf(arginitfile, MAX_SIZE-1, "--init-file=%s/init.sql", filepath); + char *fakeargv[] = {const_cast("fuzz_mysqld"), + const_cast("--user=root"), + const_cast("--secure-file-priv=NULL"), + const_cast("--log-error-verbosity=5"), + const_cast("--explicit_defaults_for_timestamp"), + //we should adapt vio_fuzz to give a socket to openssl in order to support ssl + const_cast("--skip-ssl"), + const_cast("--mysqlx=0"), + const_cast("--event-scheduler=DISABLED"), + const_cast("--performance_schema=OFF"), + const_cast("--thread_stack=1048576"), + const_cast("--datadir=/tmp/mysql/"), + const_cast("--port=3303"), + const_cast("--socket=/tmp/mysqld.sock"), + const_cast(argbase), + const_cast(arginitfile), + 0}; + int fakeargc = 15; + mysqld_main(fakeargc, fakeargv); + //terminate_compress_gtid_table_thread(); + + logfile = fopen("/dev/null", "w"); + } + // The fuzzing takes place on network data received from client + sock_initfuzz(Data,Size-1); + + Channel_info_fuzz *channel_info = new (std::nothrow) Channel_info_fuzz(Data[Size-1] & 0x80); + try_connection(channel_info); + + return 0; +} diff --git a/projects/mysql-server/targets/fuzz_mysqld.dict b/projects/mysql-server/targets/fuzz_mysqld.dict new file mode 100644 index 000000000..33c97f6ed --- /dev/null +++ b/projects/mysql-server/targets/fuzz_mysqld.dict @@ -0,0 +1 @@ +user="root" diff --git a/projects/mysql-server/targets/fuzz_mysqld.options b/projects/mysql-server/targets/fuzz_mysqld.options new file mode 100644 index 000000000..329a6e27b --- /dev/null +++ b/projects/mysql-server/targets/fuzz_mysqld.options @@ -0,0 +1,2 @@ +[libfuzzer] +close_fd_mask = 3 diff --git a/projects/mysql-server/targets/fuzz_real_query.cc b/projects/mysql-server/targets/fuzz_real_query.cc new file mode 100644 index 000000000..15a72e763 --- /dev/null +++ b/projects/mysql-server/targets/fuzz_real_query.cc @@ -0,0 +1,100 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "violite.h" + +using namespace std; +FILE *logfile = NULL; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + MYSQL mysql; + long flags; + bool opt_cleartext = true; + unsigned int opt_ssl = SSL_MODE_DISABLED; + MYSQL_RES *result; + + if (Size < sizeof(unsigned long)) { + return 0; + } + if (logfile == NULL) { + logfile = fopen("/dev/null", "w"); + } + flags = * ((unsigned long *) (Data + Size - sizeof(unsigned long))); + mysql_init(&mysql); + mysql_options(&mysql, MYSQL_ENABLE_CLEARTEXT_PLUGIN, &opt_cleartext); + mysql_options(&mysql, MYSQL_OPT_SSL_MODE, &opt_ssl); + mysql.options.protocol = MYSQL_PROTOCOL_FUZZ; + // The fuzzing takes place on network data received from server + sock_initfuzz(Data,Size - sizeof(unsigned long)); + if (!mysql_real_connect(&mysql, "localhost", "root", "root", "dbname", 0, NULL, flags)) { + goto out; + } else { + fprintf(logfile, "The last inserted row id is: %llu\n", mysql_insert_id(&mysql)); + fprintf(logfile, "%llu affected rows\n", mysql_affected_rows(&mysql)); + mysql_info(&mysql); + } + + mysql_query(&mysql, "CREATE DATABASE fuzzbase"); + if (mysql_query(&mysql, "SELECT * FROM CARS")) { + goto out; + } + result = mysql_store_result(&mysql); + if (result != NULL) { + int num_fields = mysql_num_fields(result); + MYSQL_FIELD *field; + while((field = mysql_fetch_field(result))) { + fprintf(logfile, "%s\n", field->name); + } + MYSQL_ROW row = mysql_fetch_row(result); + unsigned long * lengths = mysql_fetch_lengths(result); + while (row ) { + for(int i = 0; i < num_fields; i++) { + fprintf(logfile, "length %lu, %s\n", lengths[i], row[i] ? row[i] : "NULL"); + } + row = mysql_fetch_row(result); + } + mysql_free_result(result); + } + result = mysql_list_dbs(&mysql, NULL); + if (result) { + mysql_free_result(result); + } + result = mysql_list_tables(&mysql, NULL); + if (result) { + mysql_free_result(result); + } + result = mysql_list_fields(&mysql, "sometable", NULL); + if (result) { + mysql_free_result(result); + } + result = mysql_list_processes(&mysql); + if (result) { + mysql_free_result(result); + } + mysql_ping(&mysql); + + if (mysql_change_user(&mysql, "user", "password", "new_database")) { + goto out; + } + if (mysql_query(&mysql, "INSERT INTO Fuzzers(Name) VALUES('myfuzzer')") == 0) { + fprintf(logfile, "The last inserted row id is: %llu\n", mysql_insert_id(&mysql)); + fprintf(logfile, "%llu affected rows\n", mysql_affected_rows(&mysql)); + mysql_info(&mysql); + } + mysql_get_host_info(&mysql); + mysql_get_proto_info(&mysql); + mysql_get_server_info(&mysql); + mysql_get_server_version(&mysql); + mysql_dump_debug_info(&mysql); + mysql_sqlstate(&mysql); + mysql_stat(&mysql); + +out: + mysql_close(&mysql); + return 0; +} diff --git a/projects/mysql-server/targets/fuzz_stmt_fetch.cc b/projects/mysql-server/targets/fuzz_stmt_fetch.cc new file mode 100644 index 000000000..040610152 --- /dev/null +++ b/projects/mysql-server/targets/fuzz_stmt_fetch.cc @@ -0,0 +1,123 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "violite.h" + +using namespace std; + +#define STRING_SIZE 50 + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + MYSQL mysql; + MYSQL_BIND bind[4]; + MYSQL_RES *prepare_meta_result; + MYSQL_TIME ts; + unsigned long length[4]; + int column_count; + short small_data; + int int_data; + char str_data[STRING_SIZE]; + bool is_null[4]; + bool error[4]; + bool opt_cleartext = true; + unsigned int opt_ssl = SSL_MODE_DISABLED; + + mysql_init(&mysql); + mysql_options(&mysql, MYSQL_ENABLE_CLEARTEXT_PLUGIN, &opt_cleartext); + mysql_options(&mysql, MYSQL_OPT_SSL_MODE, &opt_ssl); + mysql.options.protocol = MYSQL_PROTOCOL_FUZZ; + // The fuzzing takes place on network data received from server + sock_initfuzz(Data,Size); + if (!mysql_real_connect(&mysql,"localhost","root","root","",0,NULL,0)) + { + return 0; + } + + MYSQL_STMT *stmt = mysql_stmt_init(&mysql); + if (!stmt) + { + mysql_stmt_close(stmt); + mysql_close(&mysql); + return 0; + } + if (mysql_stmt_prepare(stmt, "SELECT col1, col2, col3, col4 FROM Cars",(ulong)strlen("SELECT col1, col2, col3, col4 FROM Cars"))) + { + mysql_stmt_close(stmt); + mysql_close(&mysql); + return 0; + } + prepare_meta_result = mysql_stmt_result_metadata(stmt); + if (!prepare_meta_result) + { + mysql_stmt_close(stmt); + mysql_close(&mysql); + return 0; + } + + if (mysql_stmt_execute(stmt)) + { + mysql_stmt_close(stmt); + mysql_close(&mysql); + return 0; + } + column_count= mysql_num_fields(prepare_meta_result); + memset(bind, 0, sizeof(bind)); + /* INTEGER COLUMN */ + bind[0].buffer_type= MYSQL_TYPE_LONG; + bind[0].buffer= (char *)&int_data; + bind[0].is_null= &is_null[0]; + bind[0].length= &length[0]; + bind[0].error= &error[0]; + + /* STRING COLUMN */ + bind[1].buffer_type= MYSQL_TYPE_STRING; + bind[1].buffer= (char *)str_data; + bind[1].buffer_length= STRING_SIZE; + bind[1].is_null= &is_null[1]; + bind[1].length= &length[1]; + bind[1].error= &error[1]; + + /* SMALLINT COLUMN */ + bind[2].buffer_type= MYSQL_TYPE_SHORT; + bind[2].buffer= (char *)&small_data; + bind[2].is_null= &is_null[2]; + bind[2].length= &length[2]; + bind[2].error= &error[2]; + + /* TIMESTAMP COLUMN */ + bind[3].buffer_type= MYSQL_TYPE_TIMESTAMP; + bind[3].buffer= (char *)&ts; + bind[3].is_null= &is_null[3]; + bind[3].length= &length[3]; + bind[3].error= &error[3]; + + if (mysql_stmt_bind_result(stmt, bind)) + { + mysql_free_result(prepare_meta_result); + mysql_stmt_close(stmt); + mysql_close(&mysql); + return 0; + } + if (mysql_stmt_store_result(stmt)) + { + mysql_free_result(prepare_meta_result); + mysql_stmt_close(stmt); + mysql_close(&mysql); + return 0; + } + while (1) { + int status = mysql_stmt_fetch(stmt); + if (status == 1 || status == MYSQL_NO_DATA) + break; + } + + mysql_free_result(prepare_meta_result); + mysql_stmt_close(stmt); + mysql_close(&mysql); + return 0; +} diff --git a/projects/mysql-server/targets/init.sql b/projects/mysql-server/targets/init.sql new file mode 100644 index 000000000..a4ca5ce0a --- /dev/null +++ b/projects/mysql-server/targets/init.sql @@ -0,0 +1,2 @@ +CREATE USER 'fuzzuser'@'localhost' IDENTIFIED BY 'fuzzpass'; +ALTER USER 'root'@'localhost' IDENTIFIED BY 'mainpass'; diff --git a/projects/mysql-server/targets/initnopw.sql b/projects/mysql-server/targets/initnopw.sql new file mode 100644 index 000000000..7d3d3df04 --- /dev/null +++ b/projects/mysql-server/targets/initnopw.sql @@ -0,0 +1 @@ +CREATE USER 'fuzzuser'@'localhost' IDENTIFIED BY 'fuzzpass'; diff --git a/projects/mysql-server/targets/onefile.cc b/projects/mysql-server/targets/onefile.cc new file mode 100644 index 000000000..bfffa709e --- /dev/null +++ b/projects/mysql-server/targets/onefile.cc @@ -0,0 +1,50 @@ +#include +#include +#include + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); + +int main(int argc, char** argv) +{ + FILE * fp; + uint8_t *Data; + size_t Size; + + if (argc != 2) { + return 1; + } + //opens the file, get its size, and reads it into a buffer + fp = fopen(argv[1], "rb"); + if (fp == NULL) { + return 2; + } + if (fseek(fp, 0L, SEEK_END) != 0) { + fclose(fp); + return 2; + } + Size = ftell(fp); + if (Size == (size_t) -1) { + fclose(fp); + return 2; + } + if (fseek(fp, 0L, SEEK_SET) != 0) { + fclose(fp); + return 2; + } + Data = (uint8_t*)malloc(Size*sizeof(uint8_t)); + if (Data == NULL) { + fclose(fp); + return 2; + } + if (fread(Data, Size, 1, fp) != 1) { + fclose(fp); + free(Data); + return 2; + } + + //lauch fuzzer + LLVMFuzzerTestOneInput(Data, Size); + free(Data); + fclose(fp); + return 0; +}