Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-18350

Using audit plugin with MySQL, mysqld crashes when running COM_INIT_DB against invalid database

    Details

      Description

      #Environment

      MariaDB Audit Plugin 1.4 (included in MariaDB Server 10.3.9)
      MySQL 5.7.19
      CentOS 7

      #Events

      Using MariaDB Audit Plugin with MySQL, mysqld crashes when selecting a database by COM_INIT_DB which the user has no privileges for or does not exist.
      However, if you have already run COM_INIT_DB successfully against a (valid) database at least once in the connection, mysqld do not crash even if COM_INIT_DB fails after that.

      There are two ways to crash, one is "USE command" and the other is "Specifying when connecting".
      (However, when I tried MySQL 5.7.23 instead of MySQL 5.7.19, mysqld also crashed in the case of "Specifying when connecting", but in the case of "USE command" it did not crash.)


      "USE command"

      $ mysql -u test -p
      Enter password:
      Welcome to the MySQL monitor. Commands end with ; or \g.
      ...
      Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

      mysql> USE invalidDB
      ERROR 2013 (HY000): Lost connection to MySQL server during query

      "Specifying when connecting"

      $ mysql -u test -p invalidDB
      Enter password:

      ERROR 2013 (HY000): Lost connection to MySQL server at 'reading authorization packet', system error: 95

      #Stack trace (in the case of "USE command")

      01:11:04 UTC - mysqld got signal 11 ;
      This could be because you hit a bug. It is also possible that this binary
      or one of the libraries it was linked against is corrupt, improperly built,
      or misconfigured. This error can also be caused by malfunctioning hardware.
      Attempting to collect some information that could help diagnose the problem.
      As this is a crash and something is definitely wrong, the information
      collection process might fail.
       
      key_buffer_size=8388608
      read_buffer_size=131072
      max_used_connections=12
      max_threads=100
      thread_count=5
      connection_count=5
      It is possible that mysqld could use up to
      key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = 47926 K  bytes of memory
      Hope that's ok; if not, decrease some variables in the equation.
       
      Thread pointer: 0x7f712192a030
      Attempting backtrace. You can use the following information to find out
      where mysqld died. If you see no messages after this, something went
      terribly wrong...
      stack_bottom = 7f71c591ee30 thread_stack 0x40000
      /usr/sbin/mysqld(my_print_stacktrace+0x3b)[0xef7bcb]
      /usr/sbin/mysqld(handle_fatal_signal+0x461)[0x7aff11]
      /lib64/libpthread.so.0(+0x10fc0)[0x7f74d5cc4fc0]
      /lib64/libc.so.6(+0x142862)[0x7f74d473e862]
      /usr/lib64/mysql/plugin/server_audit.so(auditing+0xa31)[0x7f71c74c4341]
      /usr/lib64/mysql/plugin/server_audit.so(+0xa29b)[0x7f71c74c529b]
      /usr/sbin/mysqld(_Z18mysql_audit_notifyP3THD30mysql_event_general_subclass_tPKciS3_m+0x2a2)[0x7b0a82]
      /usr/sbin/mysqld(_ZN12Query_logger17general_log_printEP3THD19enum_server_commandPKcz+0xcc)[0xc1375c]
      /usr/sbin/mysqld(_Z15mysql_change_dbP3THDRK25st_mysql_const_lex_stringb+0x397)[0xc8d647]
      /usr/sbin/mysqld(_Z16dispatch_commandP3THDPK8COM_DATA19enum_server_command+0x8c9)[0xcc9ba9]
      /usr/sbin/mysqld(_Z10do_commandP3THD+0x19f)[0xccb79f]
      /usr/sbin/mysqld(handle_connection+0x288)[0xd8ad38]
      /usr/sbin/mysqld(pfs_spawn_thread+0x1b4)[0x126de04]
      /lib64/libpthread.so.0(+0x86e5)[0x7f74d5cbc6e5]
      /lib64/libc.so.6(clone+0x6d)[0x7f74d46f913d]
       
      Trying to get some variables.
      Some pointers may be invalid and cause the dump to abort.
      Query (0): Connection ID (thread ID): 304833
      Status: NOT_KILLED
      

      #Core dump (in the case of "USE command")

      [Thread debugging using libthread_db enabled]
      Using host libthread_db library "/lib64/libthread_db.so.1".
      Core was generated by `/usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid'.
       
      Program terminated with signal 11, Segmentation fault.
       
      #0  0x00007f51681563e1 in __pthread_kill (threadid=<optimized out>, signo=11) at ../sysdeps/unix/sysv/linux/pthread_kill.c:58
      58    val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid),
      Missing separate debuginfos, use: debuginfo-install mysql-community-server-5.7.19-1.el7.x86_64
       
      (gdb) bt
      #0  0x00007f51681563e1 in __pthread_kill (threadid=<optimized out>, signo=11) at ../sysdeps/unix/sysv/linux/pthread_kill.c:58
      #1  0x00000000007afe85 in handle_fatal_signal (sig=11) at /export/home2/pb2/build/sb_1-23948522-1498141788.79/rpm/BUILD/mysql-5.7.19/mysql-5.7.19/sql/signal_handler.cc:220
      #2  <signal handler called>
      #3  __memcpy_avx_unaligned () at ../sysdeps/x86_64/multiarch/memcpy-avx-unaligned.S:51
      #4  0x00007f4e602e7341 in memcpy (__len=255, __src=<optimized out>, __dest=0x7f4d978d3eb0) at /usr/include/bits/string3.h:51
      #5  get_str_n (src_len=255, src=<optimized out>, dest_size=256, dest_len=0x7f4d978d3fb0, dest=0x7f4d978d3eb0 "")
          at /home/buildbot/buildbot/padding_for_CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX/mariadb-10.3.9/plugin/server_audit/server_audit.c:936
      #6  update_connection_info (after_action=<synthetic pointer>, ev=0x7f4e58253a60, event_class=0, cn=0x7f4d978d3e98)
          at /home/buildbot/buildbot/padding_for_CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX/mariadb-10.3.9/plugin/server_audit/server_audit.c:1859
      #7  auditing (thd=thd@entry=0x7f4d942043b0, event_class=event_class@entry=0, ev=0x7f4e58253a60)
          at /home/buildbot/buildbot/padding_for_CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX/mariadb-10.3.9/plugin/server_audit/server_audit.c:2019
      #8  0x00007f4e602e829b in auditing_v4 (thd=0x7f4d942043b0, class=MYSQL_AUDIT_GENERAL_CLASS, ev=0x7f4e58253b80)
          at /home/buildbot/buildbot/padding_for_CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX/mariadb-10.3.9/plugin/server_audit/test_audit_v4.c:115
      #9  0x00000000007b0a82 in plugins_dispatch (arg=<synthetic pointer>, plugin=<optimized out>, thd=<optimized out>)
          at /export/home2/pb2/build/sb_1-23948522-1498141788.79/rpm/BUILD/mysql-5.7.19/mysql-5.7.19/sql/sql_audit.cc:1370
      #10 event_class_dispatch (event=0x7f4e58253b80, event_class=MYSQL_AUDIT_GENERAL_CLASS, thd=0x7f4d942043b0)
          at /export/home2/pb2/build/sb_1-23948522-1498141788.79/rpm/BUILD/mysql-5.7.19/mysql-5.7.19/sql/sql_audit.cc:1410
      #11 mysql_audit_notify (thd=thd@entry=0x7f4d942043b0, subclass=subclass@entry=MYSQL_AUDIT_GENERAL_LOG, subclass_name=subclass_name@entry=0x1421aa7 "MYSQL_AUDIT_GENERAL_LOG", 
          error_code=error_code@entry=0, msg=<optimized out>, msg_len=<optimized out>) at /export/home2/pb2/build/sb_1-23948522-1498141788.79/rpm/BUILD/mysql-5.7.19/mysql-5.7.19/sql/sql_audit.cc:460
      #12 0x0000000000c1375c in mysql_audit_general_log (cmdlen=<optimized out>, cmd=<optimized out>, thd=0x7f4d942043b0)
          at /export/home2/pb2/build/sb_1-23948522-1498141788.79/rpm/BUILD/mysql-5.7.19/mysql-5.7.19/sql/sql_audit.h:93
      #13 Query_logger::general_log_print (this=0x1e6dac0 <query_logger>, thd=thd@entry=0x7f4d942043b0, command=command@entry=COM_INIT_DB, format=<optimized out>)
          at /export/home2/pb2/build/sb_1-23948522-1498141788.79/rpm/BUILD/mysql-5.7.19/mysql-5.7.19/sql/log.cc:1501
      #14 0x0000000000c8d647 in mysql_change_db (thd=thd@entry=0x7f4d942043b0, new_db_name=..., force_switch=force_switch@entry=false)
          at /export/home2/pb2/build/sb_1-23948522-1498141788.79/rpm/BUILD/mysql-5.7.19/mysql-5.7.19/sql/sql_db.cc:1628
      #15 0x0000000000cc9ba9 in dispatch_command (thd=thd@entry=0x7f4d942043b0, com_data=com_data@entry=0x7f4e58254da0, command=COM_INIT_DB)
          at /export/home2/pb2/build/sb_1-23948522-1498141788.79/rpm/BUILD/mysql-5.7.19/mysql-5.7.19/sql/sql_parse.cc:1321
      #16 0x0000000000ccb79f in do_command (thd=thd@entry=0x7f4d942043b0) at /export/home2/pb2/build/sb_1-23948522-1498141788.79/rpm/BUILD/mysql-5.7.19/mysql-5.7.19/sql/sql_parse.cc:999
      #17 0x0000000000d8ad38 in handle_connection (arg=arg@entry=0x4787d9f0)
          at /export/home2/pb2/build/sb_1-23948522-1498141788.79/rpm/BUILD/mysql-5.7.19/mysql-5.7.19/sql/conn_handler/connection_handler_per_thread.cc:300
      #18 0x000000000126de04 in pfs_spawn_thread (arg=0x365bfc0) at /export/home2/pb2/build/sb_1-23948522-1498141788.79/rpm/BUILD/mysql-5.7.19/mysql-5.7.19/storage/perfschema/pfs.cc:2188
      #19 0x00007f51681506e5 in start_thread (arg=0x7f4e58255700) at pthread_create.c:333
      #20 0x00007f5166b8d13d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
      

      #Reason/Source

      Looking at "auditing_v4" method (plugin/server_audit/test_audit_v4.c), it passes "ev"(type is "mysql_event_general_302" defined in test_audit_v4.c) into "auditing" method (plugin/server_audit/server_audit.c), then passes it into "update_connection_info" method (plugin/server_audit/server_audit.c).
      But in the method, the "ev" is used as the type of "mysql_event_general" not the type of "mysql_event_general_302".
      And in the same method, in the case of mysql 5.7, invalid parameters(event->database.str, event->database.length) for the "mysql_event_general_302" are passed into "get_str_n" method.
      Then in the method, "memcpy" using invalid "src" and "src_len" causes segmentation fault and mysqld crashes.

      https://github.com/MariaDB/server/blob/10.3/plugin/server_audit/test_audit_v4.c#L22-L39

      struct mysql_event_general_302
      {
        unsigned int event_subclass;
        int general_error_code;
        unsigned long general_thread_id;
        const char *general_user;
        unsigned int general_user_length;
        const char *general_command;
        unsigned int general_command_length;
        const char *general_query;
        unsigned int general_query_length;
        struct charset_info_st *general_charset;
        unsigned long long general_time;
        unsigned long long general_rows;
        unsigned long long query_id;
        char *database;
        int database_length;
      };
      

      https://github.com/MariaDB/server/blob/10.3/plugin/server_audit/test_audit_v4.c#L42-L115

      static int auditing_v4(MYSQL_THD thd, mysql_event_class_t class, const void *ev)
      {
        int *subclass= (int *)ev;
        struct mysql_event_general_302 ev_302;
        .
        .
        .
          ev= &ev_302;
        .
        .
        .
        auditing(thd, (int) class, ev);    
      

      https://github.com/MariaDB/server/blob/10.3/plugin/server_audit/server_audit.c#L1978-L2019

      void auditing(MYSQL_THD thd, unsigned int event_class, const void *ev)
      {
      .
      .
      .
      update_connection_info(cn, event_class, ev, &after_action);
      

      https://github.com/MariaDB/server/blob/10.3/plugin/server_audit/server_audit.c#L1838-L1860

      static void update_connection_info(struct connection_info *cn,
          unsigned int event_class, const void *ev, int *after_action)
      {
        *after_action= 0;
       
        switch (event_class) {
        case MYSQL_AUDIT_GENERAL_CLASS:
        {
          const struct mysql_event_general *event =
            (const struct mysql_event_general *) ev;
                .
                .
                .
                if (init_db_command)
                {
                  /* Change DB */
                  if (mysql_57_started)
                    get_str_n(cn->db, &cn->db_length, sizeof(cn->db),
                        event->database.str, event->database.length);
      

      https://github.com/MariaDB/server/blob/10.3/plugin/server_audit/server_audit.c#L930-L939

      static void get_str_n(char *dest, int *dest_len, size_t dest_size,
                            const char *src, size_t src_len)
      {
        if (src_len >= dest_size)
          src_len= dest_size - 1;
       
        memcpy(dest, src, src_len);
        dest[src_len]= 0;
        *dest_len= (int)src_len;
      }
      

        Attachments

          Activity

            People

            • Assignee:
              holyfoot Alexey Botchkov
              Reporter:
              kgoto Kenta Goto
            • Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: