• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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