Closed drbugfinder-work closed 2 years ago
I worry the patch does not fix the integer overflow. The code still contains:
while (want >= (need - buf->used)) need <<= 1;
All the variables are unsigned int. If want and need are UINT_MAX and bug->used is 0, then it will loop indefinitely. Basically if want is UINT_MAX, then the while condition will be true all the time.
But checking want for UINT_MAX is not enough. You will get the same loop any time want >= need, provided need overflows at least once. At each overflow need becomes smaller and smaller until it becomes 0. Then the loop will never terminate because need will be costant 0 and not state changes at any subsequent iteration.
A note regarding correctness of the patchset: It traded a memory corruption for a data corruption. Now if yajl_buf_ensure_available() cannot fulfill the allocation, it returns an error. yajl_buf_ensure_available() is called only from yajl_buf_append() whose job is to append a data into a buffer. Now on yajl_buf_ensure_available() yajl_buf_append() silently discards the request:
void yajl_buf_append(yajl_buf buf, const void * data, unsigned int len)
{
yajl_buf_ensure_available(buf, len);
if (yajl_buf_ensure_available(buf, len)) {
return;
}
[...]
}
Hence an affected application won't crash and won't loop, but it will truncate data. A correct fix should keep propagating the error back to the application. If it is too difficult to fix it (and I guess it is because yajl cascades many calls without any mechanism for reporting errors), the bundled yajl should rather abort the process.
@ppisar can you provide a failing test case, I believe the error cascading works correctly and results in an error being returned to the application. The error is recorded on the buffer and attempts to use the data in the buffer will return an error.
/home/jhawthorn/src/yajl-ruby/lib/yajl.rb:80:in `encode': YAJL internal error: failed to allocate memory (Yajl::EncodeError)
from /home/jhawthorn/src/yajl-ruby/lib/yajl.rb:80:in `encode'
from test.rb:6:in `block in <main>'
from test.rb:5:in `loop'
from test.rb:5:in `<main>'
I see. I overlooked you are checking the failure later. In that case the error seems indeed propagated. I'm sorry for disturbing you.
Hello,
I saw CVE-2022-24795 in release notes of GHE v3.4.1, then I'm here after searching a little bit about the CVE. I have had the same remark as ppisar
about the infinite loop. Should I provide a test case for it here or send you via other private channel?
Best regards,
In context of fluentd/td-agent, we ran into an issue, where yajl is running into an infinite loop.
In gdb we could find out, that buf->len is 0 at that time, so need is 0, as well. https://github.com/brianmario/yajl-ruby/blob/7168bd79b888900aa94523301126f968a93eb3a6/ext/yajl/yajl_buf.c#L62 The method is called with the variable want=0, so the shift loop will never exit. https://github.com/brianmario/yajl-ruby/blob/7168bd79b888900aa94523301126f968a93eb3a6/ext/yajl/yajl_buf.c#L64
After digging a little bit deeper, we could see, that the malloc functions are completely missing error handling https://github.com/brianmario/yajl-ruby/blob/7168bd79b888900aa94523301126f968a93eb3a6/ext/yajl/yajl_alloc.c#L44 In our case buf->len was 0, so we assume, that the malloc call failed.