Bug 260006

Summary: Compressed user core files with large segments are truncated
Product: Base System Reporter: chorneck <chris_horneck>
Component: kernAssignee: freebsd-bugs (Nobody) <bugs>
Status: Closed FIXED    
Severity: Affects Some People CC: emaste, grahamperrin, jhibbits, markj
Priority: ---    
Version: 11.4-RELEASE   
Hardware: amd64   
OS: Any   
Attachments:
Description Flags
Test program none

Description chorneck 2021-11-23 21:29:47 UTC
Created attachment 229685 [details]
Test program

This problem can happen with kernels compiled with GZIO and sysctl kern.compress_user_cores=1.

If the program being dumped has a memory segment with size >= 0xFFFFFFFF, the segment will be silently truncated, which "damages" any memory segments written to the core file afterwards.

The root of the problem is in imgact_elf.c. The function compress_chunk accepts a length of type u_int (32-bits), while it's callers pass lengths of type size_t (64-bits). Thus, any segment with a length that cannot fit in 32-bits will be truncated.

The function compress_chunk lives on in later branches and appears to suffer the same problem.

Trivial test program that allocates a large memory segment before crashing is attached. Kernel must be compiled with GZIO and sysctl kern.compress_user_cores=1.
Comment 1 Mark Johnston freebsd_committer 2021-11-25 14:33:42 UTC
I believe this was fixed recently by https://cgit.freebsd.org/src/commit/?id=63cb9308a75b99fe057409705bc1b2ac0293f578

Looks like it still needs to be MFCed.
Comment 2 chorneck 2021-11-29 01:50:27 UTC
Sorry for the duplicate. I guess I only checked the release branches and not the main branch.
Comment 3 commit-hook freebsd_committer 2021-11-29 14:22:04 UTC
A commit in branch stable/13 references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=2949655427209b7d086eb35a92ea1e175d1b1a67

commit 2949655427209b7d086eb35a92ea1e175d1b1a67
Author:     Justin Hibbits <jhibbits@FreeBSD.org>
AuthorDate: 2021-10-01 18:39:18 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2021-11-29 14:08:11 +0000

    Fix segment size in compressing core dumps

    A core segment is bounded in size only by memory size.  On 64-bit
    architectures this means a segment can be much larger than 4GB.
    However, compress_chunk() takes only a u_int, clamping segment size to
    4GB-1, resulting in a truncated core.  Everything else, including the
    compressor internally, uses size_t, so use size_t at the boundary here.

    This dates back to the original refactor back in 2015 (r279801 /
    aa14e9b7).

    PR:             260006
    Sponsored by:   Juniper Networks, Inc.

    (cherry picked from commit 63cb9308a75b99fe057409705bc1b2ac0293f578)

 sys/kern/imgact_elf.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
Comment 4 commit-hook freebsd_committer 2021-11-29 14:22:07 UTC
A commit in branch stable/12 references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=f4777562833311b5b4c99e5dda8d50d91a514bf0

commit f4777562833311b5b4c99e5dda8d50d91a514bf0
Author:     Justin Hibbits <jhibbits@FreeBSD.org>
AuthorDate: 2021-10-01 18:39:18 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2021-11-29 14:21:19 +0000

    Fix segment size in compressing core dumps

    A core segment is bounded in size only by memory size.  On 64-bit
    architectures this means a segment can be much larger than 4GB.
    However, compress_chunk() takes only a u_int, clamping segment size to
    4GB-1, resulting in a truncated core.  Everything else, including the
    compressor internally, uses size_t, so use size_t at the boundary here.

    This dates back to the original refactor back in 2015 (r279801 /
    aa14e9b7).

    PR:             260006
    Sponsored by:   Juniper Networks, Inc.

    (cherry picked from commit 63cb9308a75b99fe057409705bc1b2ac0293f578)

 sys/kern/imgact_elf.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
Comment 5 Mark Johnston freebsd_committer 2021-11-29 14:24:58 UTC
(In reply to chorneck from comment #2)
No, this report is still useful.  I've merged the change, thanks!