| From 17de4d15687aa30c49660dc4b792b1fb4d38b569 Mon Sep 17 00:00:00 2001 |
| From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com> |
| Date: Thu, 7 Apr 2022 17:29:54 +0200 |
| Subject: [PATCH] Fix CVE-2022-24795 |
| |
| There was an integer overflow in yajl_buf_ensure_available() leading |
| to allocating less memory than requested. Then data were written past |
| the allocated heap buffer in yajl_buf_append(), the only caller of |
| yajl_buf_ensure_available(). Another result of the overflow was an |
| infinite loop without a return from yajl_buf_ensure_available(). |
| |
| yajl-ruby project, which bundles yajl, fixed it |
| <https://github.com/brianmario/yajl-ruby/pull/211> by checking for the |
| integer overflow, fortifying buffer allocations, and report the |
| failures to a caller. But then the caller yajl_buf_append() skips |
| a memory write if yajl_buf_ensure_available() failed leading to a data |
| corruption. |
| |
| A yajl fork mainter recommended calling memory allocation callbacks with |
| the large memory request and let them to handle it. But that has the |
| problem that it's not possible pass the overely large size to the |
| callbacks. |
| |
| This patch catches the integer overflow and terminates the process |
| with abort(). |
| |
| CVE: CVE-2022-24795 |
| Upstream-Status: Submitted [https://github.com/lloyd/yajl/issues/239] |
| Signed-off-by: Ross Burton <ross.burton@arm.com> |
| --- |
| src/yajl_buf.c | 12 +++++++++++- |
| 1 file changed, 11 insertions(+), 1 deletion(-) |
| |
| diff --git a/src/yajl_buf.c b/src/yajl_buf.c |
| index 1aeafde..55c11ad 100644 |
| --- a/src/yajl_buf.c |
| +++ b/src/yajl_buf.c |
| @@ -45,7 +45,17 @@ void yajl_buf_ensure_available(yajl_buf buf, size_t want) |
| |
| need = buf->len; |
| |
| - while (want >= (need - buf->used)) need <<= 1; |
| + if (((buf->used > want) ? buf->used : want) > (size_t)(buf->used + want)) { |
| + /* We cannot allocate more memory than SIZE_MAX. */ |
| + abort(); |
| + } |
| + while (want >= (need - buf->used)) { |
| + if (need >= (size_t)((size_t)(-1)<<1)>>1) { |
| + /* need would overflow. */ |
| + abort(); |
| + } |
| + need <<= 1; |
| + } |
| |
| if (need != buf->len) { |
| buf->data = (unsigned char *) YA_REALLOC(buf->alloc, buf->data, need); |
| -- |
| 2.34.1 |
| |