diff -Nru sane-backends-1.0.27/debian/changelog sane-backends-1.0.27/debian/changelog --- sane-backends-1.0.27/debian/changelog 2019-08-08 18:27:00.000000000 +0000 +++ sane-backends-1.0.27/debian/changelog 2020-08-21 15:02:07.000000000 +0000 @@ -1,3 +1,31 @@ +sane-backends (1.0.27-1~experimental3ubuntu2.3) bionic-security; urgency=medium + + * SECURITY UPDATE: multiple issues in epsonds network discovery + - debian/patches/CVE-2020-12861_12864_12866.patch: disable network + autodiscovery in backend/epsonds.conf.in. + - CVE-2020-12861 + - CVE-2020-12864 + - CVE-2020-12866 + * SECURITY UPDATE: out-of-bounds read in epsonds + - debian/patches/CVE-2020-12862.patch: do not read beyond the end of + the token in backend/epsonds-cmd.c. + - CVE-2020-12862 + * SECURITY UPDATE: out-of-bounds read in epsonds + - debian/patches/CVE-2020-12863.patch: read only up to seven hexdigits + to determine payload size in backend/epsonds-cmd.c. + - CVE-2020-12863 + * SECURITY UPDATE: heap buffer overflow in epsonds + - debian/patches/CVE-2020-12865.patch: check for overflow when reading + image data in backend/epsonds-cmd.c, backend/epsonds.c, + backend/epsonds.h. + - CVE-2020-12865 + * SECURITY UPDATE: NULL pointer dereference in epson2 + - debian/patches/CVE-2020-12867.patch: rewrite network I/O in + backend/epson2_net.c, backend/epson2_net.h. + - CVE-2020-12867 + + -- Marc Deslauriers Fri, 21 Aug 2020 11:02:07 -0400 + sane-backends (1.0.27-1~experimental3ubuntu2.2) bionic; urgency=medium * debian/patches/git-fix-discolored-bar-issue.patch: diff -Nru sane-backends-1.0.27/debian/patches/CVE-2020-12861_12864_12866.patch sane-backends-1.0.27/debian/patches/CVE-2020-12861_12864_12866.patch --- sane-backends-1.0.27/debian/patches/CVE-2020-12861_12864_12866.patch 1970-01-01 00:00:00.000000000 +0000 +++ sane-backends-1.0.27/debian/patches/CVE-2020-12861_12864_12866.patch 2020-08-21 14:54:59.000000000 +0000 @@ -0,0 +1,29 @@ +From 30b1831a28f24ab2921b9f717c66d37f02bb81cc Mon Sep 17 00:00:00 2001 +From: Olaf Meeuwissen +Date: Mon, 11 May 2020 21:07:12 +0900 +Subject: [PATCH] epsonds: Mitigate potential network related security issues. + Re #279 + +This pre-empts the possibility of triggering GHSL-2020-079, GHSL-2020-080 +and GHSL-2020-081. +--- + backend/epsonds.conf.in | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/backend/epsonds.conf.in b/backend/epsonds.conf.in +index b8b36237a..1967a00fd 100644 +--- a/backend/epsonds.conf.in ++++ b/backend/epsonds.conf.in +@@ -10,7 +10,7 @@ usb + # e.g.: + # usb 0x4b8 0x14c + +-# Network ++# Network (not yet supported!) + # + # net 192.168.1.123 +-net autodiscovery ++#net autodiscovery +-- +GitLab + diff -Nru sane-backends-1.0.27/debian/patches/CVE-2020-12862.patch sane-backends-1.0.27/debian/patches/CVE-2020-12862.patch --- sane-backends-1.0.27/debian/patches/CVE-2020-12862.patch 1970-01-01 00:00:00.000000000 +0000 +++ sane-backends-1.0.27/debian/patches/CVE-2020-12862.patch 2020-08-21 14:55:04.000000000 +0000 @@ -0,0 +1,75 @@ +From 27ea994d23ee52fe1ec1249c92ebc1080a358288 Mon Sep 17 00:00:00 2001 +From: Olaf Meeuwissen +Date: Thu, 30 Apr 2020 21:15:45 +0900 +Subject: [PATCH] epsonds: Do not read beyond the end of the token + +Addresses GHSL-2020-082, re #279. +--- + backend/epsonds-cmd.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/backend/epsonds-cmd.c b/backend/epsonds-cmd.c +index 9a4db3080..7ca660f1f 100644 +--- a/backend/epsonds-cmd.c ++++ b/backend/epsonds-cmd.c +@@ -255,18 +255,20 @@ static int decode_value(char *buf, int len) + } + + /* h000 */ +-static char *decode_binary(char *buf) ++static char *decode_binary(char *buf, int len) + { + char tmp[6]; + int hl; + + memcpy(tmp, buf, 4); + tmp[4] = '\0'; ++ len -= 4; + + if (buf[0] != 'h') + return NULL; + + hl = strtol(tmp + 1, NULL, 16); ++ if (hl > len) hl = len; + if (hl) { + + char *v = malloc(hl + 1); +@@ -279,9 +281,9 @@ static char *decode_binary(char *buf) + return NULL; + } + +-static char *decode_string(char *buf) ++static char *decode_string(char *buf, int len) + { +- char *p, *s = decode_binary(buf); ++ char *p, *s = decode_binary(buf, len); + if (s == NULL) + return NULL; + +@@ -326,20 +328,20 @@ static SANE_Status info_cb(void *userdata, char *token, int len) + + if (strncmp("PRD", token, 3) == 0) { + free(s->hw->model); +- s->hw->model = decode_string(value); ++ s->hw->model = decode_string(value, len); + s->hw->sane.model = s->hw->model; + DBG(1, " product: %s\n", s->hw->model); + /* we will free the string later */ + } + + if (strncmp("VER", token, 3) == 0) { +- char *v = decode_string(value); ++ char *v = decode_string(value, len); + DBG(1, " version: %s\n", v); + free(v); + } + + if (strncmp("S/N", token, 3) == 0) { +- char *v = decode_string(value); ++ char *v = decode_string(value, len); + DBG(1, " serial: %s\n", v); + free(v); + } +-- +GitLab + diff -Nru sane-backends-1.0.27/debian/patches/CVE-2020-12863.patch sane-backends-1.0.27/debian/patches/CVE-2020-12863.patch --- sane-backends-1.0.27/debian/patches/CVE-2020-12863.patch 1970-01-01 00:00:00.000000000 +0000 +++ sane-backends-1.0.27/debian/patches/CVE-2020-12863.patch 2020-08-21 14:55:10.000000000 +0000 @@ -0,0 +1,27 @@ +From db9480b09ea807e52029f2334769a55d4b95e45b Mon Sep 17 00:00:00 2001 +From: Olaf Meeuwissen +Date: Mon, 27 Apr 2020 18:24:56 +0900 +Subject: [PATCH] epsonds: Read only up to seven hexdigits to determine payload + size + +Addresses GHSL-2020-083, re #279. +--- + backend/epsonds-cmd.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/backend/epsonds-cmd.c b/backend/epsonds-cmd.c +index 9a4db3080..23327bb18 100644 +--- a/backend/epsonds-cmd.c ++++ b/backend/epsonds-cmd.c +@@ -117,7 +117,7 @@ esci2_check_header(const char *cmd, const char *buf, unsigned int *more) + return 0; + } + +- err = sscanf(&buf[5], "%x#", more); ++ err = sscanf(&buf[5], "%7x#", more); + if (err != 1) { + DBG(1, "cannot decode length from header\n"); + return 0; +-- +GitLab + diff -Nru sane-backends-1.0.27/debian/patches/CVE-2020-12865.patch sane-backends-1.0.27/debian/patches/CVE-2020-12865.patch --- sane-backends-1.0.27/debian/patches/CVE-2020-12865.patch 1970-01-01 00:00:00.000000000 +0000 +++ sane-backends-1.0.27/debian/patches/CVE-2020-12865.patch 2020-08-21 14:55:19.000000000 +0000 @@ -0,0 +1,63 @@ +From b9b0173409df73e235da2aa0dae5edd21fb55967 Mon Sep 17 00:00:00 2001 +From: Olaf Meeuwissen +Date: Mon, 27 Apr 2020 18:48:29 +0900 +Subject: [PATCH] epsonds: Prevent possible buffer overflow when reading image + data + +Addresses GHSL-2020-084, re #279. +--- + backend/epsonds-cmd.c | 5 +++++ + backend/epsonds.c | 12 +++++++----- + backend/epsonds.h | 1 + + 3 files changed, 13 insertions(+), 5 deletions(-) + +--- a/backend/epsonds-cmd.c ++++ b/backend/epsonds-cmd.c +@@ -878,6 +878,11 @@ esci2_img(struct epsonds_scanner *s, SAN + return parse_status; + } + ++ /* more data than was accounted for in s->buf */ ++ if (more > s->bsz) { ++ return SANE_STATUS_IO_ERROR; ++ } ++ + /* ALWAYS read image data */ + if (s->hw->connection == SANE_EPSONDS_NET) { + epsonds_net_request_read(s, more); +--- a/backend/epsonds.c ++++ b/backend/epsonds.c +@@ -1225,16 +1225,18 @@ sane_start(SANE_Handle handle) + if (s->line_buffer == NULL) + return SANE_STATUS_NO_MEM; + +- /* ring buffer for front page, twice bsz */ ++ /* transfer buffer size, bsz */ + /* XXX read value from scanner */ +- status = eds_ring_init(&s->front, (65536 * 4) * 2); ++ s->bsz = (65536 * 4); ++ ++ /* ring buffer for front page */ ++ status = eds_ring_init(&s->front, s->bsz * 2); + if (status != SANE_STATUS_GOOD) { + return status; + } + +- /* transfer buffer, bsz */ +- /* XXX read value from scanner */ +- s->buf = realloc(s->buf, 65536 * 4); ++ /* transfer buffer */ ++ s->buf = realloc(s->buf, s->bsz); + if (s->buf == NULL) + return SANE_STATUS_NO_MEM; + +--- a/backend/epsonds.h ++++ b/backend/epsonds.h +@@ -160,6 +160,7 @@ struct epsonds_scanner + Option_Value val[NUM_OPTIONS]; + SANE_Parameters params; + ++ size_t bsz; /* transfer buffer size */ + SANE_Byte *buf, *line_buffer; + ring_buffer *current, front, back; + diff -Nru sane-backends-1.0.27/debian/patches/CVE-2020-12867.patch sane-backends-1.0.27/debian/patches/CVE-2020-12867.patch --- sane-backends-1.0.27/debian/patches/CVE-2020-12867.patch 1970-01-01 00:00:00.000000000 +0000 +++ sane-backends-1.0.27/debian/patches/CVE-2020-12867.patch 2020-08-21 15:01:59.000000000 +0000 @@ -0,0 +1,244 @@ +Backport of: + +From fff83e7eacd0f27bb2d71c42488e0fd735c15ac3 Mon Sep 17 00:00:00 2001 +From: Olaf Meeuwissen +Date: Thu, 30 Apr 2020 18:24:51 +0900 +Subject: [PATCH] epson2: Rewrite network I/O + +This addresses GHSL-2020-075 as well as all other problematic code +uncovered as a result of investigating that. This includes: + +- buffer overflows due to use of unchecked lengths +- integer overflows due to type conversions +- potential memory leaks +- checking for memory allocation failures + +Re #279. +--- + backend/epson2_net.c | 140 +++++++++++++++++++++++++------------------ + backend/epson2_net.h | 4 +- + 2 files changed, 85 insertions(+), 59 deletions(-) + +--- a/backend/epson2_net.c ++++ b/backend/epson2_net.c +@@ -32,11 +32,12 @@ + + #include "sane/sanei_debug.h" + +-static int ++static ssize_t + sanei_epson_net_read_raw(Epson_Scanner *s, unsigned char *buf, ssize_t wanted, + SANE_Status *status) + { +- int ready, read = -1; ++ int ready; ++ ssize_t read = -1; + fd_set readable; + struct timeval tv; + +@@ -62,111 +63,137 @@ sanei_epson_net_read_raw(Epson_Scanner * + return read; + } + +-int +-sanei_epson_net_read(Epson_Scanner *s, unsigned char *buf, ssize_t wanted, ++static ssize_t ++sanei_epson_net_read_buf(Epson_Scanner *s, unsigned char *buf, ssize_t wanted, + SANE_Status * status) + { +- ssize_t size; + ssize_t read = 0; +- unsigned char header[12]; + +- /* read from buffer, if available */ +- if (s->netptr != s->netbuf) { +- DBG(23, "reading %lu from buffer at %p, %lu available\n", +- (u_long) wanted, s->netptr, (u_long) s->netlen); ++ DBG(23, "%s: reading up to %lu from buffer at %p, %lu available\n", ++ __func__, (u_long) wanted, s->netptr, (u_long) s->netlen); + +- memcpy(buf, s->netptr, wanted); +- read = wanted; ++ if ((size_t) wanted > s->netlen) { ++ *status = SANE_STATUS_IO_ERROR; ++ wanted = s->netlen; ++ } + +- s->netlen -= wanted; ++ memcpy(buf, s->netptr, wanted); ++ read = wanted; + +- if (s->netlen == 0) { +- DBG(23, "%s: freeing %p\n", __func__, s->netbuf); +- free(s->netbuf); +- s->netbuf = s->netptr = NULL; +- s->netlen = 0; +- } ++ s->netptr += read; ++ s->netlen -= read; ++ ++ if (s->netlen == 0) { ++ DBG(23, "%s: freeing %p\n", __func__, s->netbuf); ++ free(s->netbuf); ++ s->netbuf = s->netptr = NULL; ++ s->netlen = 0; ++ } ++ ++ return read; ++} ++ ++ssize_t ++sanei_epson_net_read(Epson_Scanner *s, unsigned char *buf, ssize_t wanted, ++ SANE_Status * status) ++{ ++ if (wanted < 0) { ++ *status = SANE_STATUS_INVAL; ++ return 0; ++ } ++ ++ size_t size; ++ ssize_t read = 0; ++ unsigned char header[12]; + +- return read; ++ /* read from remainder of buffer */ ++ if (s->netptr) { ++ return sanei_epson_net_read_buf(s, buf, wanted, status); + } + + /* receive net header */ +- size = sanei_epson_net_read_raw(s, header, 12, status); +- if (size != 12) { ++ read = sanei_epson_net_read_raw(s, header, 12, status); ++ if (read != 12) { + return 0; + } + ++ /* validate header */ + if (header[0] != 'I' || header[1] != 'S') { + DBG(1, "header mismatch: %02X %02x\n", header[0], header[1]); + *status = SANE_STATUS_IO_ERROR; + return 0; + } + ++ /* parse payload size */ + size = be32atoh(&header[6]); + +- DBG(23, "%s: wanted = %lu, available = %lu\n", __func__, +- (u_long) wanted, (u_long) size); +- + *status = SANE_STATUS_GOOD; + +- if (size == wanted) { +- +- DBG(15, "%s: full read\n", __func__); +- +- read = sanei_epson_net_read_raw(s, buf, size, status); ++ if (!s->netbuf) { ++ DBG(15, "%s: direct read\n", __func__); ++ DBG(23, "%s: wanted = %lu, available = %lu\n", __func__, ++ (u_long) wanted, (u_long) size); + +- if (s->netbuf) { +- free(s->netbuf); +- s->netbuf = NULL; +- s->netlen = 0; ++ if ((size_t) wanted > size) { ++ wanted = size; + } + +- if (read < 0) { +- return 0; +- } +- +-/* } else if (wanted < size && s->netlen == size) { */ ++ read = sanei_epson_net_read_raw(s, buf, wanted, status); + } else { +- DBG(23, "%s: partial read\n", __func__); ++ DBG(15, "%s: buffered read\n", __func__); ++ DBG(23, "%s: bufferable = %lu, available = %lu\n", __func__, ++ (u_long) s->netlen, (u_long) size); + +- read = sanei_epson_net_read_raw(s, s->netbuf, size, status); +- if (read != size) { +- return 0; ++ if (s->netlen > size) { ++ s->netlen = size; + } + +- s->netlen = size - wanted; +- s->netptr += wanted; +- read = wanted; +- +- DBG(23, "0,4 %02x %02x\n", s->netbuf[0], s->netbuf[4]); +- DBG(23, "storing %lu to buffer at %p, next read at %p, %lu bytes left\n", +- (u_long) size, s->netbuf, s->netptr, (u_long) s->netlen); ++ /* fill buffer */ ++ read = sanei_epson_net_read_raw(s, s->netbuf, s->netlen, status); ++ s->netptr = s->netbuf; ++ s->netlen = (read > 0 ? read : 0); + +- memcpy(buf, s->netbuf, wanted); ++ /* copy wanted part */ ++ read = sanei_epson_net_read_buf(s, buf, wanted, status); + } + + return read; + } + + +-int ++size_t + sanei_epson_net_write(Epson_Scanner *s, unsigned int cmd, const unsigned char *buf, + size_t buf_size, size_t reply_len, SANE_Status *status) + { + unsigned char *h1, *h2, *payload; + unsigned char *packet = malloc(12 + 8 + buf_size); + +- /* XXX check allocation failure */ ++ if (!packet) { ++ *status = SANE_STATUS_NO_MEM; ++ return 0; ++ } + + h1 = packet; + h2 = packet + 12; + payload = packet + 12 + 8; + + if (reply_len) { +- s->netbuf = s->netptr = malloc(reply_len); ++ if (s->netbuf) { ++ DBG(23, "%s, freeing %p, %ld bytes unprocessed\n", ++ __func__, s->netbuf, (u_long) s->netlen); ++ free(s->netbuf); ++ s->netbuf = s->netptr = NULL; ++ s->netlen = 0; ++ } ++ s->netbuf = malloc(reply_len); ++ if (!s->netbuf) { ++ free(packet); ++ *status = SANE_STATUS_NO_MEM; ++ return 0; ++ } + s->netlen = reply_len; +- DBG(24, "allocated %lu bytes at %p\n", +- (u_long) reply_len, s->netbuf); ++ DBG(24, "%s: allocated %lu bytes at %p\n", __func__, ++ (u_long) s->netlen, s->netbuf); + } + + DBG(24, "%s: cmd = %04x, buf = %p, buf_size = %lu, reply_len = %lu\n", +--- a/backend/epson2_net.h ++++ b/backend/epson2_net.h +@@ -4,9 +4,9 @@ + #include + #include "../include/sane/sane.h" + +-extern int sanei_epson_net_read(struct Epson_Scanner *s, unsigned char *buf, ssize_t buf_size, ++extern ssize_t sanei_epson_net_read(struct Epson_Scanner *s, unsigned char *buf, ssize_t buf_size, + SANE_Status *status); +-extern int sanei_epson_net_write(struct Epson_Scanner *s, unsigned int cmd, const unsigned char *buf, ++extern size_t sanei_epson_net_write(struct Epson_Scanner *s, unsigned int cmd, const unsigned char *buf, + size_t buf_size, size_t reply_len, + SANE_Status *status); + extern SANE_Status sanei_epson_net_lock(struct Epson_Scanner *s); diff -Nru sane-backends-1.0.27/debian/patches/series sane-backends-1.0.27/debian/patches/series --- sane-backends-1.0.27/debian/patches/series 2019-08-08 17:30:26.000000000 +0000 +++ sane-backends-1.0.27/debian/patches/series 2020-08-21 14:55:21.000000000 +0000 @@ -23,3 +23,8 @@ 0100-source_spelling.patch 0150-genesys-Fix-use-of-uninitialized-variable.patch git-fix-discolored-bar-issue.patch +CVE-2020-12861_12864_12866.patch +CVE-2020-12862.patch +CVE-2020-12863.patch +CVE-2020-12865.patch +CVE-2020-12867.patch