Project: upx (upx/upx), language: c++
Vulnerability instance: upx.cve-2021-20285
Sanitizer: address

================= Bug Report (1/2) ==================
## Source: GitHub Issue
## URL: https://github.com/upx/upx/issues/421
## Description:
Issue: upx/upx#421
Title: canPack@p_lx_elf.cpp:2571 BufferOverflow (both latest release version and devel version)
State: closed
Created by: Hustcw
Created at: 2020-11-12 12:39:35+00:00

Issue Body:
<!---

IF YOU REMOVE THIS TEMPLATE WE WILL CLOSE YOUR ISSUE WITHOUT RESPONSE.
Just read it and fill in the details we're asking, it saves so much of our time. Thanks!

-->

## What's the problem (or question)?
<!--- If describing a bug, tell us what happens instead of the expected behavior -->
<!--- If suggesting a change/improvement, explain the difference from current behavior -->
An issue was discovered in upx 3.96(**devel** branch), There is an illegal memory access in function canPack at p_lx_elf.cpp:2571. 
I also check the newest release version meet the same crash, lies at p_lx_elf.cpp:2490.

## What should have happened?
<!--- If you're describing a bug, tell us what should happen -->
<!--- If you're suggesting a change/improvement, tell us how it should work -->
no illegal memory access (crash)

## Do you have an idea for a solution?
<!--- Not obligatory, but suggest a fix/reason for the bug, -->
<!--- or ideas how to implement the addition or change -->
check the relocation_offset and do not access the illegal memory

## How can we reproduce the issue?
<!--- Provide unambiguous set of steps to reproduce this bug. Include code to reproduce, if relevant -->
1. Compile the devel branch with sanitize open
`export BUILD_TYPE_SANITIZE=1; make all`
2. Use `upx.out poc` and get crash
download the [poc](https://drive.google.com/file/d/1A-Xdx6QwEmtKij4IX3KbzNuNBnxbClYw/view?usp=sharing) here.

### source 
```c
2566                             unsigned rel_off = get_te64(&dynseg[-1+ z_rel].d_val);
2567                             Elf64_Rela *rp = (Elf64_Rela *)&file_image[rel_off];
2568                             unsigned relsz   = get_te64(&dynseg[-1+ z_rsz].d_val);
2569                             Elf64_Rela *last = (Elf64_Rela *)(relsz + (char *)rp);
2570                             for (; rp < last; ++rp) {
2571                                 unsigned r_va = get_te64(&rp->r_offset);
2572                                 if (r_va == user_init_ava) { // found the Elf64_Rela
2573                                     unsigned r_info = get_te64(&rp->r_info);
2574                                     unsigned r_type = ELF64_R_TYPE(r_info);
2575                                     if (Elf64_Ehdr::EM_AARCH64 == e_machine
2576                                     &&  R_AARCH64_RELATIVE == r_type) {
2577                                         user_init_va = get_te64(&rp->r_addend);
2578                                     }
```
the source code didn't check the **rel_off** so get an illegal rp

### debug
![image](https://user-images.githubusercontent.com/23634386/98940951-cb04b380-2526-11eb-9dd5-6734b7298007.png)

### bug report
```bash
ASAN:SIGSEGV
=================================================================
==65507==ERROR: AddressSanitizer: SEGV on unknown address 0x6300004013e8 (pc 0x00000055aff0 bp 0x0c3600003e31 sp 0x7ffc8f9b7378 T0)
    #0 0x55afef in get_le64(void const*) /home/wanghao/upx_dev/src/bele_policy.h:193
    #1 0x55afef in N_BELE_RTP::LEPolicy::get64(void const*) const /home/wanghao/upx_dev/src/bele_policy.h:194
    #2 0x49dfe2 in Packer::get_te64(void const*) const /home/wanghao/upx_dev/src/packer.h:297
    #3 0x49dfe2 in PackLinuxElf64::canPack() /home/wanghao/upx_dev/src/p_lx_elf.cpp:2571
    #4 0x5240a6 in try_pack /home/wanghao/upx_dev/src/packmast.cpp:91
    #5 0x52518f in PackMaster::visitAllPackers(Packer* (*)(Packer*, void*), InputFile*, options_t const*, void*) /home/wanghao/upx_dev/src/packmast.cpp:194
    #6 0x526d19 in PackMaster::getPacker(InputFile*) /home/wanghao/upx_dev/src/packmast.cpp:240
    #7 0x526e3c in PackMaster::pack(OutputFile*) /home/wanghao/upx_dev/src/packmast.cpp:260
    #8 0x55bede in do_one_file(char const*, char*) /home/wanghao/upx_dev/src/work.cpp:158
    #9 0x55c3ae in do_files(int, int, char**) /home/wanghao/upx_dev/src/work.cpp:271
    #10 0x403dbe in main /home/wanghao/upx_dev/src/main.cpp:1538
    #11 0x7f702527783f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2083f)
```

## Please tell us details about your environment.
<!--- Include as many relevant details about the environment you experienced the bug in -->
* UPX version used (both `upx 3.96(devel)` and `upx 3.96 release`):
* Host Operating System and version: ubuntu 16.04
* Host CPU architecture: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
* Target Operating System and version: ubuntu 16.04
* Target CPU architecture: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz


Comments:
Comment by Hustcw on 2020-11-17 11:53:30+00:00:
Any updates to fix this bug?

---

Comment by jreiser on 2020-12-11 21:40:38+00:00:
`readelf --all` shows many many problems with the `poc`, beginning with
```
readelf: upx_crash_p_lx_elf_dev_2490: Error: Reading 72027907223978242 bytes extends past end of file for string table
readelf: upx_crash_p_lx_elf_dev_2490: Warning: Size of section 28 is larger than the entire file!
readelf: upx_crash_p_lx_elf_dev_2490: Error: no .dynamic section in the dynamic segment
readelf: upx_crash_p_lx_elf_dev_2490: Warning: Virtual address 0xddff400b38 not located in any PT_LOAD segment.
readelf: upx_crash_p_lx_elf_dev_2490: Error: Unable to determine the length of the dynamic string table
readelf: upx_crash_p_lx_elf_dev_2490: Error:  bad symbol index: f5058b48 in relocreadelf: upx_crash_p_lx_elf_dev_2490: Error: Reading 16 bytes extends past end of file for version need aux (3)
readelf: upx_crash_p_lx_elf_dev_2490: Error: Reading 16 bytes extends past end of file for version need aux (3)
```
If you are running a fuzzer then please concentrate on fuzzing `upx -d` which is much more useful.

================= Bug Report (2/2) ==================
## Source: Red Hat Bugzilla
## URL: https://bugzilla.redhat.com/show_bug.cgi?id=1937787
## Description:
Bugzilla ID: 1937787
Title: CVE-2021-20285 upx: Illegal memory access in canPack function in p_lx_elf.cpp

Description
Pedro Sampaio 2021-03-11 14:52:39 UTC
A flaw was found in upx canPack in p_lx_elf.cpp in UPX 3.96 that allows attackers to cause a denial of service (SEGV or buffer overflow, and application crash) or possibly have unspecified other impacts via a crafted ELF.

Upstream issue:

https://github.com/upx/upx/issues/421


Comments:
Comment 1
Pedro Sampaio 2021-03-11 14:53:09 UTC
Created upx tracking bugs for this issue:

Affects: epel-all [bug 1937789]
Affects: fedora-all [bug 1937791]

---

Comment 2
Product Security DevOps Team 2021-03-11 17:25:50 UTC
This CVE Bugzilla entry is for community support informational purposes only as it does not affect a package in a commercially supported Red Hat product. Refer to the dependent bugs for status of those individual community products.

Build script:
#!/bin/bash -eu
# Minimized build script with only core build commands
set -eu
sed -i 's/ \&\& __clang_major__ < 15//m' /src/upx/src/util/util.cpp
mkdir -p build/debug
cd build/debug
cmake ../..
    cmake --build . --target $fuzz_basename -v

Dockerfile:
FROM hwiwonlee/secb.base:latest
RUN apt-get update && apt-get install -y make autoconf automake libtool cmake
RUN git clone https://github.com/upx/upx upx
RUN git -C upx checkout d7ba31cab8ce8d95d2c10e88d2ec787ac52005ef
WORKDIR $SRC/upx
COPY build.sh $SRC/

Additional files: