diff --git a/0002-Skip-empty-write-buffers-when-unserializing-parser.patch b/0002-Skip-empty-write-buffers-when-unserializing-parser.patch new file mode 100644 index 0000000..ffdb18d --- /dev/null +++ b/0002-Skip-empty-write-buffers-when-unserializing-parser.patch @@ -0,0 +1,74 @@ +From cd919def3bf5efeae24976752143cefc9ffc58fa Mon Sep 17 00:00:00 2001 +From: Michael Hanselmann +Date: Sun, 22 Aug 2021 21:07:36 +0200 +Subject: [PATCH] Skip empty write buffers when unserializing parser + +At commit 8490a7ac101d the following `fuzzing/usbredirparserfuzz` input causes +the instantiation of empty write buffers: + +$ base64 -d <<'EOF' > testcase6474540506021888 +QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAG +AAAAAN7/AAAACAA= +EOF + +Empty write buffers trigger all kinds of issues, in part because they cause +calls to write(2) with a zero length. + +Signed-off-by: Michael Hanselmann +--- + usbredirparser/usbredirparser.c | 26 ++++++++++++++++++++++---- + 1 file changed, 22 insertions(+), 4 deletions(-) + +diff --git a/usbredirparser/usbredirparser.c b/usbredirparser/usbredirparser.c +index edfdfd2..f08a43a 100644 +--- a/usbredirparser/usbredirparser.c ++++ b/usbredirparser/usbredirparser.c +@@ -1673,6 +1673,12 @@ int usbredirparser_unserialize(struct usbredirparser *parser_pub, + return -1; + } + ++ if (parser->write_buf_count != 0 || parser->write_buf != NULL || ++ parser->data != NULL) { ++ ERROR("unserialization must use a pristine parser"); ++ return -1; ++ } ++ + if (unserialize_int(parser, &state, &remain, &i, "length")) + return -1; + if (i != len) { +@@ -1763,16 +1769,28 @@ int usbredirparser_unserialize(struct usbredirparser *parser_pub, + return -1; + next = &parser->write_buf; + while (i) { ++ uint8_t *buf = NULL; ++ ++ l = 0; ++ if (unserialize_data(parser, &state, &remain, &buf, &l, "wbuf")) { ++ return -1; ++ } ++ ++ if (l == 0) { ++ free(buf); ++ ERROR("write buffer %d is empty", i); ++ return -1; ++ } ++ + wbuf = calloc(1, sizeof(*wbuf)); + if (!wbuf) { ++ free(buf); + ERROR("Out of memory allocating unserialize buffer"); + return -1; + } +- *next = wbuf; +- l = 0; +- if (unserialize_data(parser, &state, &remain, &wbuf->buf, &l, "wbuf")) +- return -1; ++ wbuf->buf = buf; + wbuf->len = l; ++ *next = wbuf; + next = &wbuf->next; + i--; + } +-- +1.8.3.1 + diff --git a/0003-Update-write-buffer-count-during-deserialization.patch b/0003-Update-write-buffer-count-during-deserialization.patch new file mode 100644 index 0000000..7b2be42 --- /dev/null +++ b/0003-Update-write-buffer-count-during-deserialization.patch @@ -0,0 +1,64 @@ +From b6ef53f4f4925d3aa71dc1cb828c311d0caa3c24 Mon Sep 17 00:00:00 2001 +From: Michael Hanselmann +Date: Sun, 22 Aug 2021 21:34:13 +0200 +Subject: [PATCH] Update write buffer count during deserialization + +At commit 8490a7ac the following `fuzzing/usbredirparserfuzz` input causes +an integer underflow on write_buf_count as it's not updated during +deserialization: + +``` +$ base64 -d <<'EOF' | gunzip -c > testcase6250181968920576 +H4sIAMChImECAzNkwA0YgZgTxPiPBGCSAkgK07b9YgPRLDA+EBvNYoPLuzDg +A3Cj3/xHBTc5IPJgFQz/vwNJznSGBIYQIBtJPxN29n842xbhaohtaXA7GX4z +fHsPFNVmYHiI4S8jBiKAADbfAEMOaEkCMEDArv6fBpX4gzMM/6OoxxHOWMMO +YjYiIFleosvhsxcD/IYofY/dW0AD/xPy1nWc3kpDTUsEnYPD+UQEPzHuxB78 +qWDwn0pgP8k6UvGDq0Alu7Foe0+0BYygEDBg+LwtAZhdAUAa2Kf/AwAA +EOF +``` + +Signed-off-by: Michael Hanselmann +--- + usbredirparser/usbredirparser.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/usbredirparser/usbredirparser.c b/usbredirparser/usbredirparser.c +index f08a43a..67303d0 100644 +--- a/usbredirparser/usbredirparser.c ++++ b/usbredirparser/usbredirparser.c +@@ -20,6 +20,7 @@ + */ + #include "config.h" + ++#include + #include + #include + #include +@@ -1059,6 +1060,8 @@ int usbredirparser_do_write(struct usbredirparser *parser_pub) + int w, ret = 0; + + LOCK(parser); ++ assert((parser->write_buf_count != 0) ^ (parser->write_buf == NULL)); ++ + for (;;) { + wbuf = parser->write_buf; + if (!wbuf) +@@ -1763,6 +1766,7 @@ int usbredirparser_unserialize(struct usbredirparser *parser_pub, + if (unserialize_data(parser, &state, &remain, &parser->data, &i, "data")) + return -1; + parser->data_read = i; ++ parser->write_buf_count = 0; + + /* Get the write buffer count and the write buffers */ + if (unserialize_int(parser, &state, &remain, &i, "write_buf_count")) +@@ -1792,6 +1796,7 @@ int usbredirparser_unserialize(struct usbredirparser *parser_pub, + wbuf->len = l; + *next = wbuf; + next = &wbuf->next; ++ parser->write_buf_count++; + i--; + } + +-- +1.8.3.1 + diff --git a/usbredir.spec b/usbredir.spec index c603f1c..98ca8ca 100644 --- a/usbredir.spec +++ b/usbredir.spec @@ -1,6 +1,6 @@ Name: usbredir Version: 0.8.0 -Release: 5 +Release: 6 Summary: network protocol libraries for sending USB device traffic License: LGPLv2+ and GPLv2+ URL: https://www.spice-space.org/usbredir.html @@ -12,6 +12,8 @@ Provides: %{name}-server Obsoletes: %{name}-server Patch1: 0001-CVE-2021-3700.patch +Patch2: 0002-Skip-empty-write-buffers-when-unserializing-parser.patch +Patch3: 0003-Update-write-buffer-count-during-deserialization.patch %description usbredir is the name of a network protocol for sending USB device traffic over @@ -68,6 +70,9 @@ make %{?_smp_mflags} V=1 %changelog +* Tue Dec 07 2021 wuguanghao - 0.8.0-6 +- fix timeout and abort of fuzz-test + * Thu Sep 23 2021 yanglongkang - 0.8.0-5 - fix CVE-2021-3700