Bug #87203 | Suspicious UAF at storage/innobase/row/row0merge.cc | ||
---|---|---|---|
Submitted: | 26 Jul 2017 10:03 | Modified: | 27 Jul 2017 14:43 |
Reporter: | alex chen | Email Updates: | |
Status: | Verified | Impact on me: | |
Category: | MySQL Server: InnoDB storage engine | Severity: | S3 (Non-critical) |
Version: | 5.7 | OS: | Any |
Assigned to: | CPU Architecture: | Any |
[26 Jul 2017 10:03]
alex chen
[26 Jul 2017 13:33]
MySQL Verification Team
HI! In order to proceed, I need two informations from you. First of all, what is this MySQL version exactly that you are using ????? Second, you use acronym UAF. What does it exactly stands for you ????
[26 Jul 2017 14:12]
alex chen
Thanks @Sinisa Milivojevic We focused on the source code, I believe the situation is in the master branch of version 5.7, https://github.com/mysql/mysql-server/tree/5.7 though the pieces of code are shared in serval versions. Sorry for the term UAF, it stands for Use After Free (https://cwe.mitre.org/data/definitions/416.html), it means, at this situation, Could there are any chance that Step 3 frees the memory already freed by Step 1 (is a possible execution path ) ?
[26 Jul 2017 15:14]
MySQL Verification Team
Hi! Yes, you are right that the function can be called twice. However, as it is the case with most of our memory management functions / methods, each block in heap is set to NULL on the release of the memory and checked for NULL before the release occurs. That means that you can call this function three times in a row on the same heap object without any danger.
[26 Jul 2017 16:09]
alex chen
Hi, thanks, it would be no problem if there is NULL assignment in memory release, but I couldn't sure about that, there are two suspicious lines, mem_heap_free(row_heap); // line 1 ut_free(nonnull); // line 2 for line 1, I can see there is a MAGIC number checking when freeing the blocks of a heap, but it seems cannot alter the address stored in variables `row_heap`, the function declaration is [void mem_heap_free(mem_heap_t* heap)] ? `row_heap` still keeps the address ? for line 2, ut_free is a macro of the following `deallocate` function (according to my code cross references), I couldn't find a NULL assignment inside, could it still be a problem ? https://github.com/mysql/mysql-server/blob/5.7/storage/innobase/include/ut0new.h#L391 /** Free a memory allocated by allocate() and trace the deallocation. @param[in,out] ptr pointer to memory to free @param[in] n_elements number of elements allocated (unused) */ void deallocate( pointer ptr, size_type n_elements = 0) { if (ptr == NULL) { return; } #ifdef UNIV_PFS_MEMORY ut_new_pfx_t* pfx = reinterpret_cast<ut_new_pfx_t*>(ptr) - 1; deallocate_trace(pfx); free(pfx); #else free(ptr); #endif /* UNIV_PFS_MEMORY */ }
[27 Jul 2017 14:13]
MySQL Verification Team
We did lots of analysis and concluded that ut_free() is idempotent. We are sure that it is so in non-debug mode. Debug mode still remains to be analysed, as the code path is quite different. So, this remains as "Not a Bug".
[27 Jul 2017 14:36]
MySQL Verification Team
Hi! The analysis of the code in debug mode proves that there is an improbable, but possible case where non-NULL pointer could be freed twice. Hence, this bug is also verified. Thank you for your contribution.
[27 Jul 2017 14:43]
alex chen
Hi, Thank you for your great efforts.