A customer reports a constant crash of dnf in libsolv library when listing the content of a custom repository.
The repository contains +30000 packages and a lot of files in those packages (there are 16355166 files in total, checking the XML).
Core dump analysis shows that the xd->len field, which is a int, overflows, causing the issue since it starts accessing invalid addresses.
Core dump on {appcore.usersys.redhat.com}}:
$ ssh appcore.usersys.redhat.com $ appcore-cli gdb --id 47d9d8bc725d12f98bbf68ddc618d7c4372a6ce71fdcb4b38bcf0d14aacfcb23
Analysis:
Program terminated with signal SIGSEGV, Segmentation fault. #0 0x00007f0629007b9a in data_addideof (xd=xd@entry=0x7fff10b17ec0, sx=1108886, eof=0) at ../src/repodata.c:3173 3173 *dp++ = (x >> 20) | 128; (gdb) bt #0 0x00007f0629007b9a in data_addideof (xd=xd@entry=0x7fff10b17ec0, sx=1108886, eof=0) at ../src/repodata.c:3173 #1 0x00007f062900d0a6 in repodata_serialize_key (data=data@entry=0x5623a0dabfe0, newincore=newincore@entry=0x7fff10b17ec0, newvincore=newvincore@entry=0x7fff10b17eb0, schema=schema@entry=0x5623a0dee250, key=0x5623a0cebd80, val=<optimized out>) at ../src/repodata.c:3363 #2 0x00007f062900de62 in repodata_internalize (data=data@entry=0x5623a0dabfe0) at ../src/repodata.c:3697 #3 0x00007f0629854858 in repo_add_rpmmd (repo=0x5623a083c300, fp=0x5623a06aa2f0, language=<optimized out>, flags=16) at ../ext/repo_rpmmd.c:1165 #4 0x00007f062944b849 in load_filelists_cb (repo=repo@entry=0x5623a083c300, fp=fp@entry=0x5623a06aa2f0) at /usr/src/debug/libdnf-0.69.0-8.el9_4.1.x86_64/libdnf/dnf-sack.cpp:459 #5 0x00007f0629453fb4 in load_ext (sack=sack@entry=0x5623a0c6a8e0, hrepo=hrepo@entry=0x5623a0b47e50, which_repodata=which_repodata@entry=_HY_REPODATA_FILENAMES, suffix=suffix@entry=0x7f06295083bc "-filenames", which_filename=which_filename@entry=0x7f06295083b2 "filelists", cb=cb@entry=0x7f062944b830 <load_filelists_cb(Repo*, FILE*)>, error=0x7fff10b186f8) at /usr/src/debug/libdnf-0.69.0-8.el9_4.1.x86_64/libdnf/dnf-sack.cpp:445 #6 0x00007f06294552a6 in dnf_sack_load_repo (sack=0x5623a0c6a8e0, repo=0x5623a0b47e50, flags=15, error=0x7fff10b187b8) at /usr/src/debug/libdnf-0.69.0-8.el9_4.1.x86_64/libdnf/dnf-sack.cpp:1865 #7 0x00007f0627657773 in load_repo (self=0x7f0626229e80, args=<optimized out>, kwds=<optimized out>) at /usr/src/debug/libdnf-0.69.0-8.el9_4.1.x86_64/python/hawkey/sack-py.cpp:779 [...] (gdb) p dp $2 = (unsigned char *) 0x7f03fdeaf02c <error: Cannot access memory at address 0x7f03fdeaf02c> (gdb) p xd->buf $3 = (unsigned char *) 0x7f047deaf010 "" (gdb) p xd->len $4 = -2147483621 3110 /* TODO: unify with repo_write and repo_solv! */ 3111 3112 #define EXTDATA_BLOCK 1023 3113 3114 struct extdata { 3115 unsigned char *buf; 3116 int len; <<<<<<< HERE 3117 };
Rebuilding the library with some assertions verifying that there is no overflow, I can confirm that there is int overflow occurring.
At the time of overflow, the buffer was full of filenames (without directory name, just the filenames).