Version in base suite: 2.7.0-2+deb11u1 Base version: gerbv_2.7.0-2+deb11u1 Target version: gerbv_2.7.0-2+deb11u2 Base file: /srv/ftp-master.debian.org/ftp/pool/main/g/gerbv/gerbv_2.7.0-2+deb11u1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/g/gerbv/gerbv_2.7.0-2+deb11u2.dsc changelog | 9 patches/security/CVE-2021-40393.patch | 47 ++ patches/security/CVE-2021-40394.patch | 44 ++ patches/security/CVE-2021-40401.patch | 587 ++++++++++++++++++++++++++++++++++ patches/security/CVE-2021-40403.patch | 389 ++++++++++++++++++++++ patches/series | 4 6 files changed, 1080 insertions(+) diff -Nru gerbv-2.7.0/debian/changelog gerbv-2.7.0/debian/changelog --- gerbv-2.7.0/debian/changelog 2021-12-05 08:14:05.000000000 +0000 +++ gerbv-2.7.0/debian/changelog 2022-12-09 07:47:59.000000000 +0000 @@ -1,3 +1,12 @@ +gerbv (2.7.0-2+deb11u2) bullseye-security; urgency=high + + * Non-maintainer upload by the Security Team. + * Fix multiple vulnerbilities in RS-274X processing and the pick-and-place + parsing functionality: CVE-2021-40393, CVE-2021-40394, CVE-2021-40401, + CVE-2021-40403 + + -- Aron Xu Fri, 09 Dec 2022 15:47:59 +0800 + gerbv (2.7.0-2+deb11u1) bullseye; urgency=medium * Build for bullseye diff -Nru gerbv-2.7.0/debian/patches/security/CVE-2021-40393.patch gerbv-2.7.0/debian/patches/security/CVE-2021-40393.patch --- gerbv-2.7.0/debian/patches/security/CVE-2021-40393.patch 1970-01-01 00:00:00.000000000 +0000 +++ gerbv-2.7.0/debian/patches/security/CVE-2021-40393.patch 2022-12-09 07:44:47.000000000 +0000 @@ -0,0 +1,47 @@ +commit 4d12b696aed19fbcc115fe83aa7597b7c42ba8d6 +Author: ooxi +Date: Fri Nov 19 13:54:14 2021 +0100 + + Fix CVE-2021-40393 + + A possible out-of-bounds write vulnerability was discovered by the Cisco Talos team. This patch mitigates the issue by adding bounds checking. + +Index: gerbv-2.7.0/src/gerber.c +=================================================================== +--- gerbv-2.7.0.orig/src/gerber.c ++++ gerbv-2.7.0/src/gerber.c +@@ -28,6 +28,7 @@ + + #include "gerbv.h" + ++#include + #include + #include + #include /* pow() */ +@@ -1935,14 +1936,22 @@ simplify_aperture_macro(gerbv_aperture_t + case GERBV_OPCODE_PUSH : + push(s, ip->data.fval); + break; +- case GERBV_OPCODE_PPUSH : +- push(s, lp[ip->data.ival - 1]); ++ case GERBV_OPCODE_PPUSH : { ++ ssize_t const idx = ip->data.ival - 1; ++ if ((idx < 0) || (idx >= APERTURE_PARAMETERS_MAX)) ++ GERB_FATAL_ERROR(_("Tried to access oob aperture")); ++ push(s, lp[idx]); + break; +- case GERBV_OPCODE_PPOP: ++ } ++ case GERBV_OPCODE_PPOP: { + if (pop(s, &tmp[0]) < 0) + GERB_FATAL_ERROR(_("Tried to pop an empty stack")); +- lp[ip->data.ival - 1] = tmp[0]; ++ ssize_t const idx = ip->data.ival - 1; ++ if ((idx < 0) || (idx >= APERTURE_PARAMETERS_MAX)) ++ GERB_FATAL_ERROR(_("Tried to access oob aperture")); ++ lp[idx] = tmp[0]; + break; ++ } + case GERBV_OPCODE_ADD : + if (pop(s, &tmp[0]) < 0) + GERB_FATAL_ERROR(_("Tried to pop an empty stack")); diff -Nru gerbv-2.7.0/debian/patches/security/CVE-2021-40394.patch gerbv-2.7.0/debian/patches/security/CVE-2021-40394.patch --- gerbv-2.7.0/debian/patches/security/CVE-2021-40394.patch 1970-01-01 00:00:00.000000000 +0000 +++ gerbv-2.7.0/debian/patches/security/CVE-2021-40394.patch 2022-12-09 07:46:40.000000000 +0000 @@ -0,0 +1,44 @@ +commit 8d7e005f8783d92de74192af21303619bef7541f +Author: ooxi +Date: Thu Nov 4 18:11:30 2021 +0100 + + Fix CVE-2021-40394 + + A possible signed integer overflow was discovered by the Cisco Talos team. This patch mitigates the issue by clamping the computation. + +Index: gerbv-2.7.0/src/gerber.c +=================================================================== +--- gerbv-2.7.0.orig/src/gerber.c ++++ gerbv-2.7.0/src/gerber.c +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + #include /* pow() */ + #include + #include +@@ -2002,8 +2003,22 @@ simplify_aperture_macro(gerbv_aperture_t + * - number of points defined in entry 1 of the stack + + * start point. Times two since it is both X and Y. + * - Then three more; exposure, nuf points and rotation. ++ * ++ * @warning Calculation must be guarded against signed integer ++ * overflow ++ * ++ * @see CVE-2021-40394 + */ +- nuf_parameters = ((int)s->stack[1] + 1) * 2 + 3; ++ int const sstack = (int)s->stack[1]; ++ if ((sstack < 0) || (sstack >= INT_MAX / 4)) { ++ GERB_COMPILE_ERROR(_("Possible signed integer overflow " ++ "in calculating number of parameters " ++ "to aperture macro, will clamp to " ++ "(%d)"), APERTURE_PARAMETERS_MAX); ++ nuf_parameters = APERTURE_PARAMETERS_MAX; ++ } else { ++ nuf_parameters = (sstack + 1) * 2 + 3; ++ } + break; + case 5 : + dprintf(" Aperture macro polygon [5] ("); diff -Nru gerbv-2.7.0/debian/patches/security/CVE-2021-40401.patch gerbv-2.7.0/debian/patches/security/CVE-2021-40401.patch --- gerbv-2.7.0/debian/patches/security/CVE-2021-40401.patch 1970-01-01 00:00:00.000000000 +0000 +++ gerbv-2.7.0/debian/patches/security/CVE-2021-40401.patch 2022-12-09 07:46:43.000000000 +0000 @@ -0,0 +1,587 @@ +commit 68ee18945bcf68ff964c42f12af79c5c0e2f4069 +Author: ooxi +Date: Sun Dec 19 19:24:28 2021 +0100 + + Fix TALOS-2021-1415 + + Gerbv RS-274X aperture definition tokenization use-after-free vulnerability + + ### Summary + + A use-after-free vulnerability exists in the RS-274X aperture definition tokenization functionality of Gerbv 2.7.0 and dev (commit b5f1eacd) and Gerbv forked 2.7.1. A specially-crafted gerber file can lead to code execution. An attacker can provide a malicious file to trigger this vulnerability. + ### Tested Versions + + Gerbv 2.7.0 + Gerbv forked 2.7.1 + Gerbv dev (commit b5f1eacd) + + ### Product URLs + + [https://sourceforge.net/projects/gerbv/](https://sourceforge.net/projects/gerbv/) + + ### CVSSv3 Score + + 10.0 - CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:L/A:H + + ### CWE + + CWE-252 - Unchecked Return Value + + ### Details + + Gerbv is an open-source software that allows users to view RS-274X Gerber files, Excellon drill files and pick-n-place files. These file formats are used in industry to describe the layers of a printed circuit board and are a core part of the manufacturing process. + + Some PCB (printed circuit board) manufacturers use software like Gerbv in their web interfaces as a tool to convert Gerber (or other supported) files into images. Users can upload gerber files to the manufacturer website, which are converted to an image to be displayed in the browser, so that users can verify that what has been uploaded matches their expectations. Gerbv can do such conversions using the `-x` switch (export). For this reason, we consider this software as reachable via network without user interaction or privilege requirements. + + Gerbv uses the function `gerbv_open_image` to open files. In this advisory we're interested in the RS-274X file-type. + + int + gerbv_open_image(gerbv_project_t *gerbvProject, char *filename, int idx, int reload, + gerbv_HID_Attribute *fattr, int n_fattr, gboolean forceLoadFile) + { + ... + dprintf("In open_image, about to try opening filename = %s\n", filename); + + fd = gerb_fopen(filename); + if (fd == NULL) { + GERB_COMPILE_ERROR(_("Trying to open \"%s\": %s"), + filename, strerror(errno)); + return -1; + } + ... + if (gerber_is_rs274x_p(fd, &foundBinary)) { // [1] + dprintf("Found RS-274X file\n"); + if (!foundBinary || forceLoadFile) { + /* figure out the directory path in case parse_gerb needs to + * load any include files */ + gchar *currentLoadDirectory = g_path_get_dirname (filename); + parsed_image = parse_gerb(fd, currentLoadDirectory); // [2] + g_free (currentLoadDirectory); + } + } + ... + + A file is considered of type "RS-274X" if the function `gerber_is_rs274x_p` [1] returns true. When true, the `parse_gerb` is called [2] to parse the input file. Let's first look at the requirements that we need to satisfy to have an input file be recognized as an RS-274X file: + + gboolean + gerber_is_rs274x_p(gerb_file_t *fd, gboolean *returnFoundBinary) + { + ... + while (fgets(buf, MAXL, fd->fd) != NULL) { + dprintf ("buf = \"%s\"\n", buf); + len = strlen(buf); + + /* First look through the file for indications of its type by + * checking that file is not binary (non-printing chars and white + * spaces) + */ + for (i = 0; i < len; i++) { // [3] + if (!isprint((int) buf[i]) && (buf[i] != '\r') && + (buf[i] != '\n') && (buf[i] != '\t')) { + found_binary = TRUE; + dprintf ("found_binary (%d)\n", buf[i]); + } + } + if (g_strstr_len(buf, len, "%ADD")) { + found_ADD = TRUE; + dprintf ("found_ADD\n"); + } + if (g_strstr_len(buf, len, "D00") || g_strstr_len(buf, len, "D0")) { + found_D0 = TRUE; + dprintf ("found_D0\n"); + } + if (g_strstr_len(buf, len, "D02") || g_strstr_len(buf, len, "D2")) { + found_D2 = TRUE; + dprintf ("found_D2\n"); + } + if (g_strstr_len(buf, len, "M00") || g_strstr_len(buf, len, "M0")) { + found_M0 = TRUE; + dprintf ("found_M0\n"); + } + if (g_strstr_len(buf, len, "M02") || g_strstr_len(buf, len, "M2")) { + found_M2 = TRUE; + dprintf ("found_M2\n"); + } + if (g_strstr_len(buf, len, "*")) { + found_star = TRUE; + dprintf ("found_star\n"); + } + /* look for X or Y */ + if ((letter = g_strstr_len(buf, len, "X")) != NULL) { + if (isdigit((int) letter[1])) { /* grab char after X */ + found_X = TRUE; + dprintf ("found_X\n"); + } + } + if ((letter = g_strstr_len(buf, len, "Y")) != NULL) { + if (isdigit((int) letter[1])) { /* grab char after Y */ + found_Y = TRUE; + dprintf ("found_Y\n"); + } + } + } + ... + /* Now form logical expression determining if the file is RS-274X */ + if ((found_D0 || found_D2 || found_M0 || found_M2) && // [4] + found_ADD && found_star && (found_X || found_Y)) + return TRUE; + + return FALSE; + + } /* gerber_is_rs274x */ + + For an input to be considered an RS-274X file, the file must first contain only printing characters [3]. The other requirements can be gathered by the conditional expression at [4]. An example of a minimal RS-274X file is the following: + + %FSLAX26Y26*% + %MOMM*% + %ADD100C,1.5*% + D100* + X0Y0D03* + M02* + + Even though not important for the purposes of the vulnerability itself, note that the checks use `g_strstr_len`, so all those fields can be found anywhere in the file. For example, this file is also recognized as an RS-274X file, even though it will fail later checks in the execution flow: + + %ADD0X0* + + After an RS-274X file has been recognized, `parse_gerb` is called, which in turn calls `gerber_parse_file_segment`: + + gboolean + gerber_parse_file_segment (gint levelOfRecursion, gerbv_image_t *image, + gerb_state_t *state, gerbv_net_t *curr_net, + gerbv_stats_t *stats, gerb_file_t *fd, + gchar *directoryPath) + { + ... + while ((read = gerb_fgetc(fd)) != EOF) { + ... + case '%': + dprintf("... Found %% code at line %ld\n", line_num); + while (1) { + parse_rs274x(levelOfRecursion, fd, image, state, curr_net, + stats, directoryPath, &line_num); + + If our file starts with "%", we end up calling `parse_rs274x`: + + static void + parse_rs274x(gint levelOfRecursion, gerb_file_t *fd, gerbv_image_t *image, + gerb_state_t *state, gerbv_net_t *curr_net, gerbv_stats_t *stats, + gchar *directoryPath, long int *line_num_p) + { + ... + switch (A2I(op[0], op[1])){ + ... + case A2I('A','D'): /* Aperture Description */ + a = (gerbv_aperture_t *) g_new0 (gerbv_aperture_t,1); + + ano = parse_aperture_definition(fd, a, image, scale, line_num_p); // [5] + ... + break; + case A2I('A','M'): /* Aperture Macro */ + tmp_amacro = image->amacro; + image->amacro = parse_aperture_macro(fd); + if (image->amacro) { + image->amacro->next = tmp_amacro; + ... + + For this advisory, we're interested in the `AM` and `AD` commands. For details on the Gerber format see the [specification](https://www.ucamco.com/files/downloads/file_en/81/the-gerber-file-format-specification_en.pdf) from Ucamco. + + In summary, `AM` defines a "macro aperture template", which is, in other terms, a parameterized shape. It is a flexible way to define arbitrary shapes by building on top of simpler shapes (primitives). It allows for arithmetic operations and variable definition. After a template has been defined, the `AD` command is used to instantiate the template and optionally passes some parameters to customize the shape. + + From the specification, this is the syntax of the `AM` command: + + = AM* + = {{*}{*}} + = $K= + = ,{,}| + = $M|< Arithmetic expression> + = 0 + + While this is the syntax for the `AD` command: + + = ADD