[mysql] Initial integration for mysql server (#2593)

* Initial integration for mysql server
This commit is contained in:
Catena cyber 2019-08-01 22:27:38 +02:00 committed by jonathanmetzman
parent 50390b7fb5
commit 276d4c7888
14 changed files with 880 additions and 0 deletions

View File

@ -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

View File

@ -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 .. -DDOWNLOAD_BOOST=1 -DWITH_BOOST=$WORK -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 --datadir=$OUT/mysql/data --basedir=$OUT/mysql/

View File

@ -0,0 +1,363 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 758df9761e8..837a8c6b071 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -461,6 +461,7 @@ ENDIF()
OPTION(DISABLE_SHARED
"Don't build shared libraries, compile code as position-dependent" OFF)
+OPTION(FUZZING "Fuzzing" OFF)
IF(DISABLE_SHARED)
MESSAGE("Dynamic plugins are disabled.")
ENDIF()
@@ -1140,6 +1141,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 561960cd925..a11ccb42299 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -260,7 +260,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 b0c5c6958ba..7ef140dc163 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
};
/**
@@ -457,4 +459,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 2606e908124..20a80adcd5b 100644
--- a/libmysql/CMakeLists.txt
+++ b/libmysql/CMakeLists.txt
@@ -319,7 +319,7 @@ IF(NOT DISABLE_SHARED)
ENDIF()
GET_TARGET_PROPERTY(libmysql_link_flags libmysql LINK_FLAGS)
- IF(LINK_FLAG_NO_UNDEFINED)
+ IF(LINK_FLAG_NO_UNDEFINED AND NOT FUZZING)
SET(libmysql_link_flags
"${libmysql_link_flags} ${LINK_FLAG_NO_UNDEFINED}")
SET(libmysql_link_flags
diff --git a/mysys_ssl/my_rnd.cc b/mysys_ssl/my_rnd.cc
index d4b3ec4b851..aaaf8bdb93c 100644
--- a/mysys_ssl/my_rnd.cc
+++ b/mysys_ssl/my_rnd.cc
@@ -50,6 +50,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);
@@ -66,6 +69,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) {
@@ -89,6 +98,10 @@ int my_rand_buffer(unsigned char *buffer, size_t buffer_size) {
double my_rnd_ssl(struct rand_struct *rand_st) {
unsigned int res;
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ return 34.56;
+#endif
+
if (my_rand_buffer((unsigned char *)&res, sizeof(res)))
return my_rnd(rand_st);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 13479e3c474..5d165982fe6 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -6124,7 +6124,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
@@ -6598,8 +6600,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 */
@@ -6771,6 +6775,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
@@ -9501,6 +9509,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/vio/CMakeLists.txt b/vio/CMakeLists.txt
index f46858dd4bf..09c0a62ef8c 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 de46703eb82..01e8695f574 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;
@@ -577,7 +598,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..d8c2987d7be
--- /dev/null
+++ b/vio/viofuzz.cc
@@ -0,0 +1,128 @@
+
+#include "my_config.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <time.h>
+#ifndef _WIN32
+#include <netdb.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+
+#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 <sys/filio.h>
+#endif
+#ifndef _WIN32
+#include <netinet/tcp.h>
+#endif
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#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, wait;
+ int retry_count = 0;
+ 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 %d ", size);
+ for (int i=0; i<size; i++)
+ printf("%02x ", bufp[i]);
+ printf("\n");
+#endif
+ return size;
+}
+
+size_t vio_write_buff_fuzz(Vio *vio, const uchar *bufp, size_t size) {
+ DBUG_ENTER("vio_write_buff_fuzz\n");
+#ifdef FUZZ_DEBUG
+ printf("net srv %d ", size);
+ for (int i=0; i<size; i++)
+ printf("%02x ", bufp[i]);
+ printf("\n");
+#endif
+ return size;
+}
+
+bool vio_is_connected_fuzz(Vio *vio) {
+ DBUG_ENTER("vio_is_connected_fuzz\n");
+ return (fuzzPos < fuzzSize);
+}
+
+bool vio_was_timeout_fuzz(Vio *vio) {
+ DBUG_ENTER("vio_was_timeout_fuzz\n");
+ return false;
+}
+
+int vio_shutdown_fuzz(Vio *vio) {
+ DBUG_ENTER("vio_shutdown_fuzz");
+ return 0;
+}
+
+int vio_keepalive_fuzz(Vio *vio, bool set_keep_alive) {
+ DBUG_ENTER("vio_keepalive_fuzz\n");
+ return 0;
+}
+int vio_io_wait_fuzz(Vio *vio, enum enum_vio_io_event event, int timeout) {
+ DBUG_ENTER("vio_io_wait_fuzz");
+ return 1;
+}
+
+int vio_fastsend_fuzz(Vio *vio) {
+ DBUG_ENTER("vio_fastsend_fuzz\n");
+ return 0;
+}
+
+bool vio_should_retry_fuzz(Vio *vio) {
+ DBUG_ENTER("vio_should_retry_fuzz\n");
+ return (fuzzPos < fuzzSize);
+}

View File

@ -0,0 +1,12 @@
homepage: "https://www.mysql.com"
primary_contact: "secalert_us@oracle.com"
auto_ccs :
- "p.antoine@catenacyber.fr"
- "christopher.alves@telecomnancy.net"
- "zouhair.janati-idrissi@telecomnancy.net"
- "julien.zhan@telecomnancy.net"
sanitizers:
- address
- memory
- undefined

View File

@ -0,0 +1,24 @@
find_library(FUZZINGENGINE_LIB FuzzingEngine)
if(NOT FUZZINGENGINE_LIB)
MYSQL_ADD_EXECUTABLE(fuzz_real_query fuzz_real_query.cc onefile.cc)
TARGET_LINK_LIBRARIES(fuzz_real_query mysqlclient)
MYSQL_ADD_EXECUTABLE(fuzz_stmt_fetch fuzz_stmt_fetch.cc onefile.cc)
TARGET_LINK_LIBRARIES(fuzz_stmt_fetch mysqlclient)
MYSQL_ADD_EXECUTABLE(fuzz_mysqld fuzz_mysqld.cc onefile.cc)
TARGET_LINK_LIBRARIES(fuzz_mysqld sql_main sql_gis binlog rpl master slave sql_main sql_dd sql_gis mysys mysys_ssl binlogevents_static ${ICU_LIBRARIES})
else()
MYSQL_ADD_EXECUTABLE(fuzz_real_query fuzz_real_query.cc)
TARGET_LINK_LIBRARIES(fuzz_real_query mysqlclient)
TARGET_LINK_LIBRARIES(fuzz_real_query FuzzingEngine)
MYSQL_ADD_EXECUTABLE(fuzz_stmt_fetch fuzz_stmt_fetch.cc)
TARGET_LINK_LIBRARIES(fuzz_stmt_fetch mysqlclient)
TARGET_LINK_LIBRARIES(fuzz_stmt_fetch FuzzingEngine)
MYSQL_ADD_EXECUTABLE(fuzz_mysqld fuzz_mysqld.cc)
TARGET_LINK_LIBRARIES(fuzz_mysqld sql_main sql_gis binlog rpl master slave sql_main sql_dd sql_gis mysys mysys_ssl binlogevents_static ${ICU_LIBRARIES})
TARGET_LINK_LIBRARIES(fuzz_mysqld FuzzingEngine)
endif()

View File

@ -0,0 +1,2 @@
This is the directory used for fuzzing, intended to be used with oss-fuzz.

View File

@ -0,0 +1,98 @@
//#include <stdint.h>
//#include <stdlib.h>
//#include <stdio.h>
//#include <string>
//#include <iostream>
//#include <mysql.h>
//#include <mysql/client_plugin.h>
//#include <mysqld_error.h>
#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 "violite.h"
#include <stdlib.h>
using namespace std;
FILE *logfile = NULL;
Connection_handler_manager * chm;
extern int mysqld_main(int argc, char **argv);
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; }
};
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");
system("cp -r /out/mysql/data /tmp/mysql");
char *fakeargv[] = {const_cast<char *>("fuzz_mysqld"),
const_cast<char *>("--user=root"),
const_cast<char *>("--secure-file-priv=NULL"),
const_cast<char *>("--log-error-verbosity=5"),
const_cast<char *>("--explicit_defaults_for_timestamp"),
//we should adapt vio_fuzz to give a socket to openssl in order to support ssl
const_cast<char *>("--skip-ssl"),
const_cast<char *>("--mysqlx=0"),
const_cast<char *>("--event-scheduler=DISABLED"),
const_cast<char *>("--thread_stack=1048576"),
const_cast<char *>("--datadir=/tmp/mysql/"),
const_cast<char *>("--basedir=/out/mysql/"),
const_cast<char *>("--init-file=/out/init.sql"),
0};
int fakeargc = 12;
mysqld_main(fakeargc, fakeargv);
chm = Connection_handler_manager::get_instance();
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);
chm->process_new_connection(channel_info);
return 0;
}

View File

@ -0,0 +1 @@
user="root"

View File

@ -0,0 +1,2 @@
[libfuzzer]
close_fd_mask = 3

View File

@ -0,0 +1,100 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <iostream>
#include <mysql.h>
#include <mysql/client_plugin.h>
#include <mysqld_error.h>
#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;
}

View File

@ -0,0 +1,55 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <iostream>
#include <mysql.h>
#include <mysql/client_plugin.h>
#include <conn_handler/connection_handler.h>
#include "violite.h"
using namespace std;
FILE *logfile = NULL;
Connection_handler * connection_handler;
class Channel_info_fuzz : public Channel_info {
bool m_is_admin_conn;
protected:
virtual Vio *create_and_init_vio() const {
Vio *vio = mysql_socket_vio_new(0, VIO_TYPE_FUZZ, 0);
return vio;
}
public:
Channel_info_fuzz(bool is_admin_conn) : m_is_admin_conn(is_admin_conn) {}
virtual THD *create_thd() {
THD *thd = Channel_info::create_thd();
if (thd != NULL) {
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; }
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
if (Size < 1) {
return 0;
}
if (logfile == NULL) {
connection_handler = new (std::nothrow) One_thread_connection_handler();
logfile = fopen("/dev/null", "w");
}
// The fuzzing takes place on network data received from server
sock_initfuzz(Data,Size-1);
Channel_info_fuzz *channel_info = new (std::nothrow) Channel_info_fuzz(Data[Size-1] & 0x80);
connection_handler->add_connection(channel_info);
return 0;
}

View File

@ -0,0 +1,115 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <iostream>
#include <mysql.h>
#include <mysql/client_plugin.h>
#include <mysqld_error.h>
#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 param_count, column_count, row_count;
short small_data;
int int_data;
char str_data[STRING_SIZE];
bool is_null[4];
bool error[4];
mysql_init(&mysql);
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 (!mysql_stmt_fetch(stmt)) {}
mysql_free_result(prepare_meta_result);
mysql_stmt_close(stmt);
mysql_close(&mysql);
return 0;
}

View File

@ -0,0 +1,2 @@
CREATE USER 'fuzzuser'@'localhost' IDENTIFIED BY 'fuzzpass';
ALTER USER 'root'@'localhost' IDENTIFIED BY 'mainpass';

View File

@ -0,0 +1,50 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
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;
}