1 /* Copyright 2020 Google Inc.
2
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 */
15
16 //#include <stdint.h>
17 //#include <stdlib.h>
18 //#include <stdio.h>
19 //#include <string>
20 //#include <iostream>
21 //#include <mysql.h>
22 //#include <mysql/client_plugin.h>
23 //#include <mysqld_error.h>
24 #include "sql/sql_class.h"
25 #include "sql/protocol_classic.h"
26 #include "sql/conn_handler/channel_info.h"
27 #include "sql/conn_handler/connection_handler.h"
28 #include "sql/conn_handler/connection_handler_manager.h"
29 #include "sql/conn_handler/init_net_server_extension.h"
30 #include "sql/conn_handler/connection_handler_impl.h"
31 #include "sql/mysqld.h"
32 #include "sql/set_var.h"
33 #include "sql/rpl_handler.h"
34 #include "sql/log.h"
35 #include "sql/opt_costconstantcache.h"
36 #include "sql/sql_plugin.h"
37 #include "sql/sql_thd_internal_api.h"
38 #include "sql/mysqld_thd_manager.h"
39 #include "sql/sql_parse.h"
40 #include "mysql/psi/mysql_socket.h"
41 #include "violite.h"
42 #include "util_fuzz.h"
43 #include <stdlib.h>
44 #include <libgen.h>
45
46 using namespace std;
47 FILE *logfile = NULL;
48 Connection_handler_manager * chm;
49 extern int mysqld_main(int argc, char **argv);
50 char *filepath = NULL;
51
LLVMFuzzerInitialize(const int * argc,char *** argv)52 extern "C" int LLVMFuzzerInitialize(const int* argc, char*** argv) {
53 filepath = dirname(strdup((*argv)[0]));
54 return 0;
55 }
56
57
58 // FIXME: Fix this buffer with succesful authenticated connection for mysql 8.21.
59 const uint8_t startConn[] =
60 "\xa6\x00\x00\x01\x85\xa6\xff\x01\x00\x00\x00\x01\x2d\x00\x00\x00" \
61 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
62 "\x00\x00\x00\x00\x72\x6f\x6f\x74\x00\x01\x00\x6d\x79\x73\x71\x6c" \
63 "\x5f\x63\x6c\x65\x61\x72\x5f\x70\x61\x73\x73\x77\x6f\x72\x64\x00" \
64 "\x69\x04\x5f\x70\x69\x64\x05\x35\x34\x30\x30\x31\x03\x5f\x6f\x73" \
65 "\x08\x6f\x73\x78\x31\x30\x2e\x31\x33\x09\x5f\x70\x6c\x61\x74\x66" \
66 "\x6f\x72\x6d\x06\x78\x38\x36\x5f\x36\x34\x0f\x5f\x63\x6c\x69\x65" \
67 "\x6e\x74\x5f\x76\x65\x72\x73\x69\x6f\x6e\x06\x38\x2e\x30\x2e\x31" \
68 "\x36\x0c\x5f\x63\x6c\x69\x65\x6e\x74\x5f\x6e\x61\x6d\x65\x08\x6c" \
69 "\x69\x62\x6d\x79\x73\x71\x6c\x0c\x70\x72\x6f\x67\x72\x61\x6d\x5f" \
70 "\x6e\x61\x6d\x65\x05\x6d\x79\x73\x71\x6c"
71 "\x00\x00\x00\x03"
72 ;
73
74
75 class Channel_info_fuzz : public Channel_info {
76 bool m_is_admin_conn;
77
78 protected:
create_and_init_vio() const79 virtual Vio *create_and_init_vio() const {
80 Vio *vio = vio_new(0, VIO_TYPE_FUZZ, VIO_LOCALHOST);
81 return vio;
82 }
83
84 public:
Channel_info_fuzz(bool is_admin_conn)85 Channel_info_fuzz(bool is_admin_conn) : m_is_admin_conn(is_admin_conn) {}
86
create_thd()87 virtual THD *create_thd() {
88 Vio *vio_tmp = create_and_init_vio();
89 if (vio_tmp == NULL) return NULL;
90
91 THD *thd = new (std::nothrow) THD();
92 if (thd == NULL) {
93 vio_delete(vio_tmp);
94 return NULL;
95 }
96 thd->get_protocol_classic()->init_net(vio_tmp);
97 thd->set_admin_connection(m_is_admin_conn);
98 init_net_server_extension(thd);
99 return thd;
100 }
101
is_admin_connection() const102 virtual bool is_admin_connection() const { return m_is_admin_conn; }
103 };
104
105 #define MAX_SIZE 256
106
107
LLVMFuzzerTestOneInput(const uint8_t * Data,size_t Size)108 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
109 if (Size < 1) {
110 return 0;
111 }
112 if (logfile == NULL) {
113 my_progname = "fuzz_docommand";
114 /* first init was run with
115 * mysqld --user=root --initialize-insecure --log-error-verbosity=5 --datadir=/out/mysql/data/ --basedir=/out/mysql/
116 */
117 utilfuzz_rmrf("/tmp/mysql_docommand");
118 char command[MAX_SIZE];
119 char argbase[MAX_SIZE];
120 char arginitfile[MAX_SIZE];
121 snprintf(command, MAX_SIZE-1, "%s/mysql/data", filepath);
122 utilfuzz_cpr(command, "/tmp/mysql_docommand");
123
124 snprintf(argbase, MAX_SIZE-1, "--basedir=%s/mysql/", filepath);
125 snprintf(arginitfile, MAX_SIZE-1, "--init-file=%s/initnopw.sql", filepath);
126
127 char *fakeargv[] = {const_cast<char *>("fuzz_docommand"),
128 const_cast<char *>("--user=root"),
129 const_cast<char *>("--secure-file-priv=NULL"),
130 const_cast<char *>("--log-error-verbosity=5"),
131 const_cast<char *>("--explicit_defaults_for_timestamp"),
132 //we should adapt vio_fuzz to give a socket to openssl in order to support ssl
133 const_cast<char *>("--skip-ssl"),
134 const_cast<char *>("--mysqlx=0"),
135 const_cast<char *>("--event-scheduler=DISABLED"),
136 const_cast<char *>("--performance_schema=OFF"),
137 const_cast<char *>("--thread_stack=1048576"),
138 const_cast<char *>("--datadir=/tmp/mysql_docommand/"),
139 const_cast<char *>("--port=3301"),
140 const_cast<char *>("--socket=/tmp/docommand.sock"),
141 const_cast<char *>(argbase),
142 const_cast<char *>(arginitfile),
143 0};
144 int fakeargc = 15;
145 mysqld_main(fakeargc, fakeargv);
146
147 chm = Connection_handler_manager::get_instance();
148 logfile = fopen("/dev/null", "w");
149 }
150 Channel_info_fuzz * channel_info = new (std::nothrow) Channel_info_fuzz(true);
151 sock_initfuzz(startConn,sizeof(startConn));
152 if (my_thread_init()) {
153 channel_info->send_error_and_close_channel(ER_OUT_OF_RESOURCES, 0, false);
154 abort();
155 }
156
157 THD *thd_fuzz = channel_info->create_thd();
158 if (thd_fuzz == NULL) {
159 channel_info->send_error_and_close_channel(ER_OUT_OF_RESOURCES, 0, false);
160 abort();
161 }
162
163 thd_fuzz->set_new_thread_id();
164 thd_set_thread_stack(thd_fuzz, (char *)&thd_fuzz);
165 thd_fuzz->store_globals();
166 mysql_thread_set_psi_id(thd_fuzz->thread_id());
167 mysql_socket_set_thread_owner(
168 thd_fuzz->get_protocol_classic()->get_vio()->mysql_socket);
169 Global_THD_manager *thd_manager = Global_THD_manager::get_instance();
170 thd_manager->add_thd(thd_fuzz);
171 if (thd_prepare_connection(thd_fuzz)) {
172 abort();
173 }
174 delete channel_info;
175
176 // The fuzzing takes place on network data received from client
177 sock_initfuzz(Data,Size);
178
179 while (thd_connection_alive(thd_fuzz)) {
180 if (do_command(thd_fuzz)) break;
181 }
182 end_connection(thd_fuzz);
183 close_connection(thd_fuzz, 0, false, false);
184 thd_fuzz->release_resources();
185 thd_manager->remove_thd(thd_fuzz);
186 delete thd_fuzz;
187
188 return 0;
189 }
190