//#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 "util_fuzz.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/ */ utilfuzz_rmrf("/tmp/mysqld"); char command[MAX_SIZE]; char argbase[MAX_SIZE]; char arginitfile[MAX_SIZE]; snprintf(command, MAX_SIZE-1, "%s/mysql/data", filepath); utilfuzz_cpr(command, "/tmp/mysqld"); 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/mysqld/"), 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; }