Bug 1678288 (CVE-2019-8355)

Summary: CVE-2019-8355 sox: integer overflow in xmalloc.h
Product: [Other] Security Response Reporter: Dhananjay Arunesh <darunesh>
Component: vulnerabilityAssignee: Red Hat Product Security <security-response-team>
Status: CLOSED ERRATA QA Contact:
Severity: low Docs Contact:
Priority: low    
Version: unspecifiedCC: felix, hhorak, hobbes1069, jkucera
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2021-10-27 03:25:16 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On: 1678289, 1680086    
Bug Blocks: 1678305    

Description Dhananjay Arunesh 2019-02-18 12:47:05 UTC
An issue was discovered in SoX 14.4.2. In xmalloc.h, there is an integer overflow on the result of multiplication fed into the lsx_valloc macro that wraps malloc. When the buffer is allocated, it is smaller than expected, leading to a heap-based buffer overflow in channels_start in remix.c.

Reference:
https://sourceforge.net/p/sox/bugs/320

Comment 1 Dhananjay Arunesh 2019-02-18 12:47:16 UTC
Created sox tracking bugs for this issue:

Affects: fedora-all [bug 1678289]

Comment 2 Scott Gayou 2019-02-22 17:00:13 UTC
So, for this flaw, we get to lsx_realloc with the following newsize:

```
   │30      void *lsx_realloc(void *ptr, size_t newsize)                                               │
   │31      {                                                                                          │
  >│32        if (ptr && newsize == 0) {                                                               │
   │33          free(ptr);                                                                             │
   │34          return NULL;                                                                           │
   │35        }

(gdb) print newsize
$11 = 17179869184
```
The system tries, and fails, to allocate 17 gigabytes and we exit.

We get to realloc with the large size via:

```
   │232           unsigned in_per_out = (effp->in_signal.channels +                                    │
   │233               num_out_channels - 1 - j) / num_out_channels;                                    │
  >│234           lsx_valloc(p->out_specs[j].in_specs, in_per_out);

(gdb) print effp->in_signal.channels
$12 = 1073741824
```

The size grows via the lsx_valloc macro:

```c
#define lsx_valloc(v,n)  v = lsx_malloc((n)*sizeof(*(v)))
```

On a 64-bit platform, we have 1073741824 * 16 via the sizeof *in_specs

```
(gdb) print sizeof(*(p->out_specs[j].in_specs))
$14 = 16
```

which gets us the 17179869184 value that runs us out of memory.

To potentially exploit this, we'd need to wrap around the calculation.

(gdb) ptype in_per_out
type = unsigned	int

Max size on our platform is going to be 4294967295. * 16 is 68719476720, which will fit nicely in size_t.

So I believe this is only potentially exploitable on 32-bit platforms. This could still be considered a denial of service on 64-bit (maybe, arguably, etc.), so I'll leave this open as valid for now.