Sudheer Vinukonda created TS-3286:
-------------------------------------
Summary: Improve MIOBuffer allocation mechanism with checks to
prevent corrupting the freelist
Key: TS-3286
URL: https://issues.apache.org/jira/browse/TS-3286
Project: Traffic Server
Issue Type: Improvement
Components: Core
Reporter: Sudheer Vinukonda
This jira is a follow up on TS-3285. While investigating TS-3285, I realized
that there are not sufficient guards in-place in the MIOBuffer
allocation/access mechanism to prevent corrupting the free list or accessing
the objects off of the freelist.
These issues are particularly problematic, when creating the MIOBuffer using
new_empty_MIOBuffer(). This simply pulls out the MIOBuffer from the freelist,
without resetting/initializing the data members. So, if the MIOBuffer on the
freelist is bad, then the newly allocated buffer will run into trouble (e.g
TS-3285). Note that, if the MIOBuffer is allocated using new_MIOBuffer(), it
calls clear() which resets the members correctly.
The problem also is partly due to the fact that MIOBuffer uses ProxyAllocator
and when the object is allocated from the local thread freelist, it is not
reset with a prototype object memcpy (like the ClassAllocator would do).
Some checks/asserts I am thinking of adding are as below:
{code}
diff --git a/iocore/eventsystem/IOBuffer.cc b/iocore/eventsystem/IOBuffer.cc
index 879e8ba..d54080f 100644
--- a/iocore/eventsystem/IOBuffer.cc
+++ b/iocore/eventsystem/IOBuffer.cc
@@ -82,6 +82,7 @@ MIOBuffer::remove_append(IOBufferReader * r)
int64_t
MIOBuffer::write(const void *abuf, int64_t alen)
{
+ ink_release_assert(size_index < BUFFER_SIZE_NOT_ALLOCATED);
const char *buf = (const char*)abuf;
int64_t len = alen;
while (len) {
@@ -135,6 +136,7 @@
MIOBuffer::write_and_transfer_left_over_space(IOBufferReader * r, int64_t alen,
int64_t
MIOBuffer::write(IOBufferReader * r, int64_t alen, int64_t offset)
{
+ ink_release_assert(size_index < BUFFER_SIZE_NOT_ALLOCATED);
int64_t len = alen;
IOBufferBlock *b = r->block;
offset += r->start_offset;
diff --git a/iocore/eventsystem/I_IOBuffer.h b/iocore/eventsystem/I_IOBuffer.h
index 0e5fe0c..d9aba81 100644
--- a/iocore/eventsystem/I_IOBuffer.h
+++ b/iocore/eventsystem/I_IOBuffer.h
@@ -1126,8 +1126,6 @@ public:
_writer->realloc_xmalloc(buf_size);
}
- int64_t size_index;
-
/**
Determines when to stop writing or reading. The watermark is the
level to which the producer (filler) is required to fill the buffer
@@ -1138,6 +1136,8 @@ public:
*/
int64_t water_mark;
+ int64_t size_index;
+
Ptr<IOBufferBlock> _writer;
IOBufferReader readers[MAX_MIOBUFFER_READERS];
diff --git a/iocore/eventsystem/P_IOBuffer.h b/iocore/eventsystem/P_IOBuffer.h
index 365486f..74ea432 100644
--- a/iocore/eventsystem/P_IOBuffer.h
+++ b/iocore/eventsystem/P_IOBuffer.h
@@ -775,8 +775,7 @@ TS_INLINE MIOBuffer * new_MIOBuffer_internal(
TS_INLINE void
free_MIOBuffer(MIOBuffer * mio)
{
- mio->_writer = NULL;
- mio->dealloc_all_readers();
+ clear();
THREAD_FREE(mio, ioAllocator, this_thread());
}
@@ -893,6 +892,7 @@ MIOBuffer::append_block_internal(IOBufferBlock * b)
// It would be nice to remove an empty buffer at the beginning,
// but this breaks HTTP.
// if (!_writer || !_writer->read_avail())
+ ink_release_assert(size_index < BUFFER_SIZE_NOT_ALLOCATED);
if (!_writer) {
_writer = b;
init_readers();
{code}
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)