List:Commits« Previous MessageNext Message »
From:Mats Kindahl Date:November 8 2007 1:53pm
Subject:Re: bk commit to 5.0 - BUG#31793
View as plain text  
Sven Sandberg wrote:
> Hi Mats,
>
> The patch improves the situation by not crashing on the particular 
> binlog attached to the bug report. But there are still many ways that 
> similar errors could occur:

Unfortunately, yes. There's a big bunch of missing checks in that file, 
so many that I deem it unfeasible to fix all of them, since it requires 
a significant amount of work to find and fix. We need a more thorough 
change of the code (on the level of abolishing use of memcpy() in favor 
of our own safe version) to make sure that all is patched.

I will fix the ones you mention below and spend some effort to find 
other more blatant ones, and then commit another patch. We need to get a 
patch for the most obvious ones out, so that we can do some significant 
refactoring instead of constantly patching existing code.

Just my few cents,
Mats Kindahl

>
>  - Each status case in the `switch (*pos++)' in this Query_log_event 
> constructor can potentially read beyond `end'. I'd suggest adding a 
> macro like this:
>
> #define ENSURE_SPACE(N)       \
>   do {                        \
>     if (pos + N > end) {      \
>       query = 0;              \
>       DBUG_VOID_RETURN;       \
>     }                         \
>   } while (0);
>
> And use it like this:
>
> @@ log_event.cc:1496
>     case Q_FLAGS2_CODE:
>       flags2_inited= 1;
> +     ENSURE_SPACE(4);
>       flags2= uint4korr(pos);
>       DBUG_PRINT("info",("In Query_log_event, read flags2: %lu", 
> (ulong) flags2));
>       pos+= 4;
>       break;
>
> etc.
>
>  - The same should be tested for catalog and timezone too.
>
>  - Other event types have similar problems. E.g., 
> Load_log_event::copy_log_event should check field_block_len, 
> table_name_len, and fname_len.
>
> /Sven
>
>
> Mats Kindahl wrote:
>> Patch submitted manually
>>
>>
>> ------------------------------------------------------------------------
>>
>> # This is a BitKeeper generated diff -Nru style patch.
>> #
>> # ChangeSet
>> #   2007/11/07 14:59:24+01:00 mats@stripped #   BUG#31793 (log 
>> event corruption causes crash):
>> #   #   When running mysqlbinlog on a 64-bit machine with a corrupt 
>> relay log,
>> #   it causes mysqlbinlog to crash. In this case, the crash is caused
>> #   because a request for 18446744073709534806U bytes is issued, which
>> #   apparantly can be served on a 64-bit machine (speculatively, I 
>> assume)
>> #   but this causes the memcpy() issued later to copy the data to 
>> segfault.
>> #   #   The request for the number of bytes is caused by a computation
>> #   of data_len - server_vars_len where server_vars_len is corrupt in 
>> such
>> #   a sense that it is > data_len. This causes a wrap-around, with the
>> #   the data_len given above.
>> #   #   This patch adds a check that if server_vars_len is greater than
>> #   data_len before the substraction, and aborts reading the event in
>> #   that case marking the event as invalid. # # 
>> mysql-test/std_data/corrupt-relay-bin.000624
>> #   2007/11/07 14:58:30+01:00 mats@stripped +2033 -0
>> #   BitKeeper file 
>>
> /home/mats/devel/b31793-mysql-5.0-rpl/mysql-test/std_data/corrupt-relay-bin.000624 
>>
>> # # mysql-test/std_data/corrupt-relay-bin.000624
>> #   2007/11/07 14:58:30+01:00 mats@stripped +0 -0
>> # # mysql-test/t/mysqlbinlog.test
>> #   2007/11/07 14:59:22+01:00 mats@stripped +4 -0
>> #   Adding test that it fails gracefully for a corrupt relay log.
>> # # sql/log_event.cc
>> #   2007/11/07 14:59:22+01:00 mats@stripped +11 -0
>> #   Adding check that status var length does not cause wrap-around
>> #   when performing subtraction.
>> # Binary files a/mysql-test/std_data/corrupt-relay-bin.000624 and 
>> b/mysql-test/std_data/corrupt-relay-bin.000624 differ
>> diff -Nru a/mysql-test/t/mysqlbinlog.test 
>> b/mysql-test/t/mysqlbinlog.test
>> --- a/mysql-test/t/mysqlbinlog.test    2007-11-07 15:00:13 +01:00
>> +++ b/mysql-test/t/mysqlbinlog.test    2007-11-07 15:00:13 +01:00
>> @@ -237,4 +237,8 @@
>>  --echo $c
>>  drop table t1;
>>  
>> +echo shell> mysqlbinlog std_data/corrupt-relay-bin.000624 > 
>> var/tmp/bug31793.sql;
>> +error 1;
>> +exec $MYSQL_BINLOG $MYSQL_TEST_DIR/std_data/corrupt-relay-bin.000624 
>> > $MYSQLTEST_VARDIR/tmp/bug31793.sql;
>> +
>>  --echo End of 5.0 tests
>> diff -Nru a/sql/log_event.cc b/sql/log_event.cc
>> --- a/sql/log_event.cc    2007-11-07 15:00:13 +01:00
>> +++ b/sql/log_event.cc    2007-11-07 15:00:13 +01:00
>> @@ -1475,6 +1475,17 @@
>>    if (tmp)
>>    {
>>      status_vars_len= uint2korr(buf + Q_STATUS_VARS_LEN_OFFSET);
>> +    /*
>> +      Check if status variable length is corrupt and will lead to very
>> +      wrong data. We could be even more strict and require data_len to
>> +      be even bigger, but this will suffice to catch most corruption
>> +      errors that can lead to a crash.
>> +    */
>> +    if (status_vars_len >= data_len + 1)
>> +    {
>> +      query= 0;
>> +      DBUG_VOID_RETURN;
>> +    }
>>      data_len-= status_vars_len;
>>      DBUG_PRINT("info", ("Query_log_event has status_vars_len: %u",
>>                          (uint) status_vars_len));
>>
>>
>>
>> ------------------------------------------------------------------------
>>
>>
>


-- 
Mats Kindahl
Lead Software Developer
Replication Team
MySQL AB, www.mysql.com


Thread
bk commit to 5.0 - BUG#31793Mats Kindahl7 Nov
  • Re: bk commit to 5.0 - BUG#31793Sven Sandberg8 Nov
    • Re: bk commit to 5.0 - BUG#31793Mats Kindahl8 Nov
    • Re: bk commit to 5.0 - BUG#31793Mats Kindahl8 Nov
      • Re: bk commit to 5.0 - BUG#31793Andrei Elkin9 Nov
        • Re: bk commit to 5.0 - BUG#31793Mats Kindahl9 Nov
          • Re: bk commit to 5.0 - BUG#31793Andrei Elkin9 Nov