Bug 1943409 - CVE-2021-32491 djvulibre: Integer overflow in function render() in tools/ddjvu via crafted djvu file [fedora-all]
Summary: CVE-2021-32491 djvulibre: Integer overflow in function render() in tools/ddjv...
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: Fedora
Classification: Fedora
Component: djvulibre
Version: rawhide
Hardware: x86_64
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Marek Kašík
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks: CVE-2021-32491
TreeView+ depends on / blocked
 
Reported: 2021-03-26 02:04 UTC by 1vanChen
Modified: 2021-11-25 15:21 UTC (History)
1 user (show)

Fixed In Version: djvulibre-3.5.27-24.fc32 djvulibre-3.5.27-27.fc33
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2021-11-25 15:21:18 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)
poc file (423 bytes, image/vnd.djvu+multipage)
2021-03-26 02:04 UTC, 1vanChen
no flags Details
Path fixing the integer overflow (711 bytes, patch)
2021-04-08 11:53 UTC, Marek Kašík
no flags Details | Diff

Description 1vanChen 2021-03-26 02:04:37 UTC
Created attachment 1766465 [details]
poc file

To Reproduce

```shell
./ddjvu ./poc.djvu
```

Debug Info

```shell
# ./ddjvu ./poc.djvu
=================================================================
==25519==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7ffff206583e at pc 0x000000437a6e bp 0x7fffffffe0f0 sp 0x7fffffffd8b8
READ of size 117023 at 0x7ffff206583e thread T0
    #0 0x437a6d in fwrite /local/mnt/workspace/tmp/final/llvm-project/compiler-rt/lib/asan/../sanitizer_common/sanitizer_common_interceptors.inc:1141:16
    #1 0x4ce10a in render(ddjvu_page_s*, int) /src/djvulibre-ddjvu/tools/ddjvu.cpp:435:15
    #2 0x4d3743 in dopage(int) /src/djvulibre-ddjvu/tools/ddjvu.cpp:759:3
    #3 0x4d4717 in parse_pagespec(char const*, int, void (*)(int)) /src/djvulibre-ddjvu/tools/ddjvu.cpp:825:11
    #4 0x4df19b in main /src/djvulibre-ddjvu/tools/ddjvu.cpp:1214:3
    #5 0x7ffff651a83f in __libc_start_main /build/glibc-e6zv40/glibc-2.23/csu/../csu/libc-start.c:291
    #6 0x41eff8 in _start (/mnt/disk/out/djvulibre-ddjvu/ddjvu_asan+0x41eff8)

0x7ffff206583e is located 0 bytes to the right of 213659710-byte region [0x7fffe54a2800,0x7ffff206583e)
allocated by thread T0 here:
    #0 0x498e4d in malloc /local/mnt/workspace/tmp/final/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:145:3
    #1 0x4cd9d7 in render(ddjvu_page_s*, int) /src/djvulibre-ddjvu/tools/ddjvu.cpp:397:25
    #2 0x4d3743 in dopage(int) /src/djvulibre-ddjvu/tools/ddjvu.cpp:759:3
    #3 0x4d4717 in parse_pagespec(char const*, int, void (*)(int)) /src/djvulibre-ddjvu/tools/ddjvu.cpp:825:11
    #4 0x4df19b in main /src/djvulibre-ddjvu/tools/ddjvu.cpp:1214:3
    #5 0x7ffff651a83f in __libc_start_main /build/glibc-e6zv40/glibc-2.23/csu/../csu/libc-start.c:291

SUMMARY: AddressSanitizer: heap-buffer-overflow /local/mnt/workspace/tmp/final/llvm-project/compiler-rt/lib/asan/../sanitizer_common/sanitizer_common_interceptors.inc:1141:16 in fwrite
Shadow bytes around the buggy address:
  0x10007e404ab0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007e404ac0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007e404ad0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007e404ae0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10007e404af0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x10007e404b00: 00 00 00 00 00 00 00[06]fa fa fa fa fa fa fa fa
  0x10007e404b10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x10007e404b20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x10007e404b30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x10007e404b40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x10007e404b50: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==25519==ABORTING
```

`rowsize * rrect.h` will cause integer overflow:

```shell
[----------------------------------registers-----------------------------------]
RAX: 0x7ffff7f93000 --> 0x0
RBX: 0x3e36d
RCX: 0x14bcf
RDX: 0x1d2
RSI: 0x1
RDI: 0xcbc303e
^^^^^^^^^^^^^^
RBP: 0x7fffffffe320 --> 0x7fffffffe360 --> 0x7fffffffe3d0 --> 0x7fffffffe420 --> 0x6d9620 (<__libc_csu_init>:   push   r15)
RSP: 0x7fffffffe240 --> 0x1
RIP: 0x42ac55 (<_Z6renderP12ddjvu_page_si+4885>:        call   0x4061a0 <malloc@plt>)
R8 : 0x7ffff68bebc8 --> 0x7ffff68bebb8 --> 0x12c0b70 --> 0x6245e0 (<_ZN4DJVU6DArrayINS_11GUTF8StringEE6insertEPviiPKvi>:        push   rbp)
R9 : 0x0
R10: 0x7ffff68beb78 --> 0x12c6280 --> 0x120ffffff
R11: 0x7ffff68beb78 --> 0x12c6280 --> 0x120ffffff
R12: 0xffff
R13: 0x0
R14: 0xff
R15: 0x1
EFLAGS: 0xa03 (CARRY parity adjust zero sign trap INTERRUPT direction OVERFLOW)
[-------------------------------------code-------------------------------------]
   0x42ac4c <_Z6renderP12ddjvu_page_si+4876>:   mov    r14b,0xff
   0x42ac4f <_Z6renderP12ddjvu_page_si+4879>:   mov    edi,DWORD PTR [rbp-0x64]
   0x42ac52 <_Z6renderP12ddjvu_page_si+4882>:   imul   edi,ebx
=> 0x42ac55 <_Z6renderP12ddjvu_page_si+4885>:   call   0x4061a0 <malloc@plt>
   0x42ac5a <_Z6renderP12ddjvu_page_si+4890>:   test   rax,rax
   0x42ac5d <_Z6renderP12ddjvu_page_si+4893>:   je     0x42e99c <_Z6renderP12ddjvu_page_si+20572>
   0x42ac63 <_Z6renderP12ddjvu_page_si+4899>:   mov    r12,rax
   0x42ac66 <_Z6renderP12ddjvu_page_si+4902>:   call   0x428f10 <_Z5ticksv>
Guessed arguments:
arg[0]: 0xcbc303e
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffe240 --> 0x1
0008| 0x7fffffffe248 --> 0x7fffffffe7d9 ("test.djvu")
0016| 0x7fffffffe250 --> 0x40efffe000000000
0024| 0x7fffffffe258 --> 0x3fe8a3de6ea1296b
0032| 0x7fffffffe260 --> 0x12c5310 --> 0x1
0040| 0x7fffffffe268 --> 0x0
0048| 0x7fffffffe270 --> 0x12c2730 --> 0x6e57d8 --> 0x4927c0 (<_ZN4DJVU12ddjvu_page_sD2Ev>:     push   rbp)
0056| 0x7fffffffe278 --> 0x0
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
0x000000000042ac55      397       if (! (image = (char*)malloc(rowsize * rrect.h)))
gdb-peda$

rrect.h: 0x14c76 rowsize: 0x3e36d
>>> hex(0x14c76*0x3e36d)
'0x50cbc303e'

```



Environment:

- version : djvulibre master (ee314b880c926e884be77d53ee459d9850c9c7f0)
- OS: Ubuntu 16.04
- clang version: 11


Credit: 1vanChen of NSFOCUS Security Team

Comment 1 Marek Kašík 2021-04-08 11:53:21 UTC
Created attachment 1770218 [details]
Path fixing the integer overflow

This patch casts the computation of allocated space to size_t and also checks overflow in the range of size_t (since malloc's argument is size_t).

Comment 2 1vanChen 2021-04-11 12:48:07 UTC
(In reply to Marek Kašík from comment #1)
> Created attachment 1770218 [details]
> Path fixing the integer overflow
> 
> This patch casts the computation of allocated space to size_t and also
> checks overflow in the range of size_t (since malloc's argument is size_t).


When I apply this patch, using the default compilation parameters will produce the following error:
```shell
In file included from /usr/include/c++/5/cstdint:35:0,
                 from ddjvu.cpp:73:
/usr/include/c++/5/bits/c++0x_warning.h:32:2: error: #error This file requires compiler and library support for the ISO C++ 2011 standard. This support must be enabled with the -std=c++11 or -std=gnu++11 compiler options.
 #error This file requires compiler and library support \
  ^
ddjvu.cpp: In function ‘void render(ddjvu_page_t*, int)’:
ddjvu.cpp:398:26: error: ‘SIZE_MAX’ was not declared in this scope
   if ((size_t) rowsize > SIZE_MAX / rrect.h)
```
It seems that we need to modify the default compilation parameters.

Another question: Is it necessary for us to check whether `rrect.h` is 0 to avoid division by zero errors?

Comment 3 Marek Kašík 2021-04-23 11:04:44 UTC
(In reply to 1vanChen from comment #2)
> (In reply to Marek Kašík from comment #1)
> > Created attachment 1770218 [details]
> > Path fixing the integer overflow
> > 
> > This patch casts the computation of allocated space to size_t and also
> > checks overflow in the range of size_t (since malloc's argument is size_t).
> 
> 
> When I apply this patch, using the default compilation parameters will
> produce the following error:
> ```shell
> In file included from /usr/include/c++/5/cstdint:35:0,
>                  from ddjvu.cpp:73:
> /usr/include/c++/5/bits/c++0x_warning.h:32:2: error: #error This file
> requires compiler and library support for the ISO C++ 2011 standard. This
> support must be enabled with the -std=c++11 or -std=gnu++11 compiler options.
>  #error This file requires compiler and library support \
>   ^
> ddjvu.cpp: In function ‘void render(ddjvu_page_t*, int)’:
> ddjvu.cpp:398:26: error: ‘SIZE_MAX’ was not declared in this scope
>    if ((size_t) rowsize > SIZE_MAX / rrect.h)
> ```
> It seems that we need to modify the default compilation parameters.

Hi, could you try whether including <stdint.h> instead of <cstdint> fixes the issue?
 
> Another question: Is it necessary for us to check whether `rrect.h` is 0 to
> avoid division by zero errors?

Yes, I think that we should check this because of the division.

Comment 4 1vanChen 2021-04-23 16:04:33 UTC
> Hi, could you try whether including <stdint.h> instead of <cstdint> fixes
> the issue?


Yes, thanks for your answer, it looks good now!

Comment 5 Ben Cotton 2021-11-04 14:03:03 UTC
This message is a reminder that Fedora 33 is nearing its end of life.
Fedora will stop maintaining and issuing updates for Fedora 33 on 2021-11-30.
It is Fedora's policy to close all bug reports from releases that are no longer
maintained. At that time this bug will be closed as EOL if it remains open with a
Fedora 'version' of '33'.

Package Maintainer: If you wish for this bug to remain open because you
plan to fix it in a currently maintained version, simply change the 'version' 
to a later Fedora version.

Thank you for reporting this issue and we are sorry that we were not 
able to fix it before Fedora 33 is end of life. If you would still like 
to see this bug fixed and are able to reproduce it against a later version 
of Fedora, you are encouraged  change the 'version' to a later Fedora 
version prior this bug is closed as described in the policy above.

Although we aim to fix as many bugs as possible during every release's 
lifetime, sometimes those efforts are overtaken by events. Often a 
more recent Fedora release includes newer upstream software that fixes 
bugs or makes them obsolete.

Comment 6 Ben Cotton 2021-11-04 14:32:15 UTC
This message is a reminder that Fedora 33 is nearing its end of life.
Fedora will stop maintaining and issuing updates for Fedora 33 on 2021-11-30.
It is Fedora's policy to close all bug reports from releases that are no longer
maintained. At that time this bug will be closed as EOL if it remains open with a
Fedora 'version' of '33'.

Package Maintainer: If you wish for this bug to remain open because you
plan to fix it in a currently maintained version, simply change the 'version' 
to a later Fedora version.

Thank you for reporting this issue and we are sorry that we were not 
able to fix it before Fedora 33 is end of life. If you would still like 
to see this bug fixed and are able to reproduce it against a later version 
of Fedora, you are encouraged  change the 'version' to a later Fedora 
version prior this bug is closed as described in the policy above.

Although we aim to fix as many bugs as possible during every release's 
lifetime, sometimes those efforts are overtaken by events. Often a 
more recent Fedora release includes newer upstream software that fixes 
bugs or makes them obsolete.

Comment 7 Ben Cotton 2021-11-04 15:29:57 UTC
This message is a reminder that Fedora 33 is nearing its end of life.
Fedora will stop maintaining and issuing updates for Fedora 33 on 2021-11-30.
It is Fedora's policy to close all bug reports from releases that are no longer
maintained. At that time this bug will be closed as EOL if it remains open with a
Fedora 'version' of '33'.

Package Maintainer: If you wish for this bug to remain open because you
plan to fix it in a currently maintained version, simply change the 'version' 
to a later Fedora version.

Thank you for reporting this issue and we are sorry that we were not 
able to fix it before Fedora 33 is end of life. If you would still like 
to see this bug fixed and are able to reproduce it against a later version 
of Fedora, you are encouraged  change the 'version' to a later Fedora 
version prior this bug is closed as described in the policy above.

Although we aim to fix as many bugs as possible during every release's 
lifetime, sometimes those efforts are overtaken by events. Often a 
more recent Fedora release includes newer upstream software that fixes 
bugs or makes them obsolete.

Comment 8 Marek Kašík 2021-11-25 15:21:18 UTC
This has been fixed quite some time ago (since Fedora 32).


Note You need to log in before you can comment on or make changes to this bug.