-
-
Notifications
You must be signed in to change notification settings - Fork 54
Denial of Service in Gerbv #191
Description
Summary
Error or warning while processing an included image may result in a crash of Gerbv.
CWEs
- CWE-824: Access of uninitialized pointer
Details
The Gerber RS-274X format defines the IF command (INCLUDE FILE, for referencing an external file) in its User's Guide (page 28). A valid line using this command respects the format below:
%IF<filename>.<extension>*%
The implementation of this functionality leverages two utilities:
- A
gerb_file_tstructure wrapping up details about an opened file, such as the file descriptor, filename, and data to be read; and - A
gerb_fopenfunction (fromgerb_file.c) that takes a filename and returns a (partially-initialized)gerb_fopenstructure;
The relevant execution flow in the context of this issue is as follows:
- A
gerbv_open_imagefunction (fromgerbv.c) is initially called inmain.cthrough a proxy function calledmain_open_project_from_filename. - The
gerbv_open_imageinternally callsgerb_fopenand stores the filename as a structural member infd->filename = g_strdup(filename). - In a call to
gerber_is_rs274x_p, the file is checked to respect the RS-274X format. - If it respects the format,
parse_gerbis called. parse_gerbcallsgerber_parse_file_segment.- If any command having a
%is detected,parse_rs274xis called. - If the command is detected to be
IF, then the file is read withgerb_fopen. gerber_parse_file_segmentis called again, this time having as argument a filename stored inside the initially-read file.
The issue resides in the fact that, compared to the second step, the eighth one does not set the filename. When the latter is accessed in further processing, an invalid address is dereferenced, which results in a crash of the program.
A code path achieving this is when the included files contain an invalid M-code (for example, M09*). Usually, despite the invalid code, the execution should continue without processing the erroneous information, but Gerbv executes the following in its parse_M_code:
gerbv_stats_printf(stats->error_list, GERBV_MESSAGE_ERROR, -1,
_("Encountered unknown M%02d code at line %ld in file \"%s\""),
op_int, *line_num_p, fd->filename);
As it can be observed, the fd->filename is accessed in a logging call, so the execution will crash instead of raising a warning and continuing. This will not happen if the random value found on heap and implicitly assigned to fd->filename is NULL. Most compilers have a check against this scenario, and will only print (null).
Affected Releases
The functionality of processing IF commands was introduced in a5b8484, which corresponds to v2.4.0.
PoC
For reproducing this, Cisco's parse_aperture_strtok.1.poc from CVE-2021-40401 was used as the file provided as an input parameter. The content of parse_aperture_strtok.2.poc was replaced with M09*.
As the issue depends on the random value of the unitialized fd->filename, it was reproduced by launching gdb, setting a breakpoint on gerb_fopen, and setting fd->filename to the value 0x0101010101 (a random value that could be found on the heap). Gerbv will generate a crash as follows:
$ gdb ./gerbv
[...]
(gdb) c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0x0000fffff7376590 in ?? () from /lib/aarch64-linux-gnu/libc.so.6
(gdb) bt
#0 0x0000fffff7376590 in () at /lib/aarch64-linux-gnu/libc.so.6
#1 0x0000fffff734b848 in () at /lib/aarch64-linux-gnu/libc.so.6
#2 0x0000fffff735cd78 in () at /lib/aarch64-linux-gnu/libc.so.6
#3 0x0000fffff73cfa3c in __vasprintf_chk () at /lib/aarch64-linux-gnu/libc.so.6
#4 0x0000fffff7648064 in g_vasprintf () at /usr/lib/aarch64-linux-gnu/libglib-2.0.so.0
#5 0x0000fffff761da88 in g_strdup_vprintf () at /usr/lib/aarch64-linux-gnu/libglib-2.0.so.0
#6 0x0000fffff7fa3d04 in gerbv_stats_printf (list=0xaaaaaab2ab20, type=GERBV_MESSAGE_ERROR, layer=-1, text=0xfffff7fb5830 "Encountered unknown M%02d code at line %ld in file \"%s\"") at gerb_stats.c:242
#7 0x0000fffff7fa7088 in parse_M_code (fd=0xaaaaaab2ced0, image=0xaaaaaab16fc0, line_num_p=0xffffffffe0f0) at gerber.c:1183
#8 0x0000fffff7fa487c in gerber_parse_file_segment
(levelOfRecursion=2, image=0xaaaaaab16fc0, state=0xaaaaaab16f60, curr_net=0xaaaaaab2af60, stats=0xaaaaaab2aa70, fd=0xaaaaaab2ced0, directoryPath=0xaaaaaab14a60 "/home/gerbv/triggers")
at gerber.c:172
#9 0x0000fffff7fa7f40 in parse_rs274x
(levelOfRecursion=1, fd=0xaaaaaab149a0, image=0xaaaaaab16fc0, state=0xaaaaaab16f60, curr_net=0xaaaaaab2af60, stats=0xaaaaaab2aa70, directoryPath=0xaaaaaab14a60 "/home/gerbv/triggers", line_num_p=0xffffffffe350) at gerber.c:1459
#10 0x0000fffff7fa4bec in gerber_parse_file_segment
(levelOfRecursion=1, image=0xaaaaaab16fc0, state=0xaaaaaab16f60, curr_net=0xaaaaaab2af60, stats=0xaaaaaab2aa70, fd=0xaaaaaab149a0, directoryPath=0xaaaaaab14a60 "/home/gerbv/triggers")
at gerber.c:245
#11 0x0000fffff7fa60a8 in parse_gerb (fd=0xaaaaaab149a0, directoryPath=0xaaaaaab14a60 "/home/gerbv/triggers") at gerber.c:770
#12 0x0000fffff7facca0 in gerbv_open_image
(gerbvProject=0xaaaaaab14940, filename=0xffffffffed6e "/home/gerbv/triggers/CVE-2021-40401.1.poc", idx=0, reload=0, fattr=0x0, n_fattr=0, forceLoadFile=1) at gerbv.c:527
#13 0x0000fffff7fabf44 in gerbv_open_layer_from_filename_with_color
(gerbvProject=0xaaaaaab14940, filename=0xffffffffed6e "/home/gerbv/triggers/CVE-2021-40401.1.poc", red=29555, green=29555, blue=57054, alpha=45489) at gerbv.c:249
#14 0x0000aaaaaaacb334 in main (argc=6, argv=0xffffffffe8e8) at main.c:937Impact
Gerbv can be crashed when processing files.
Suggestions for Patching
The filename can be attached to the gerb_file_t structure in gerb_fopen to avoid invalid dereferencing.