Skip to content

Fix NULL pointer dereference in solv_chksum_free()#623

Merged
mlschroe merged 1 commit into
openSUSE:masterfrom
m-blaha:libdnf-test-coredump
May 28, 2026
Merged

Fix NULL pointer dereference in solv_chksum_free()#623
mlschroe merged 1 commit into
openSUSE:masterfrom
m-blaha:libdnf-test-coredump

Conversation

@m-blaha

@m-blaha m-blaha commented May 28, 2026

Copy link
Copy Markdown
Contributor

Commit a4f1b2f ("Split the checksum implementation into chksum_impl.c") introduced a NULL pointer dereference in solv_chksum_free(). The refactoring added an else branch that accesses chk->impl to free internal resources, but this branch is reached even when chk is NULL.

Before the refactoring, solv_chksum_free(NULL, NULL) was safe:

  • the "if (cp)" branch was skipped (cp is NULL)
  • solv_free(NULL) was called, which is a no-op

After the refactoring:

  • the "if (cp)" branch is skipped
  • the new "else if (chk->impl)" dereferences chk, which is NULL

Fix by adding a NULL check for chk at the top of solv_chksum_free(), restoring the pre-refactoring behavior.

We noticed segfaults while running libdnf tests after the 0.7.38 release:

#0  0x00007f1bbfb9c53a in solv_chksum_free (chk=0x0, cp=0x0) at /usr/src/debug/libsolv-0.7.38-1.fc43.git.3779.df73dc8.x86_64/src/chksum.c:156
#1  0x00007f1bbfaefc84 in repo_add_rpm (repo=0x15222460, rpm=0x15322410 "/tmp/hawkeyxoe3yS/null.rpm", flags=1089539)
    at /usr/src/debug/libsolv-0.7.38-1.fc43.git.3779.df73dc8.x86_64/ext/repo_rpmdb.c:1988
        sigdsize = 1504
        sigcnt = 51
        sigpad = 4
        l = 0
        pool = 0x15190970
        s = 0x151a82c8
        state = {pool = 0x15190970, rootdir = 0x0, rpmhead = 0x0, rpmheadsize = 0, dbenvopened = 0, dbpath = 0x0, dbpath_allocated = 0, ts = 0x0, mi = 0x0}
        payloadformat = 0x152d71de "cpio"
        fp = 0x151f74d0
        lead = "\3757zXZ\000\000\n\341\373\f\241\002\000!\001\022\000\000\000#\270\207,\340\004\243\001(]\000\030\r\335\004b2\371u\v\200\242\275\017Q\006{\304J\361\f\362\027\"-\301\370\316\335\006\020\205w'=6\323U}Ee\f\fR\271jR/l9\276\246\037+\2628\n\321\336\024;p\025\201x\314'\027\356\374\267-\231-\005\024\320\n+\213Ӻ\adW}\224\215\206\270\224\343T\262\255\000\003\215\036\245o\3405G\277s\237\333k\235\033\324-\226$\223\200&\357\212\t\341h\\bbm\364T\353\261\333\354w\306\331\003\025\215\2045L\322B\275+p\226\346\303\021\027\nV\032\363X>\326T\202t~\356lY\344E\001\373\320"...
        headerstart = 280
        headerend = 2616
        stb = {st_dev = 47, st_ino = 80770, st_nlink = 1, st_mode = 33188, st_uid = 112180, st_gid = 112180, __pad0 = 0, st_rdev = 0, st_size = 0, st_blksize = 4096, st_blocks = 0, st_atim = {tv_sec = 1779957968, tv_nsec = 822132595}, st_mtim = {tv_sec = 1779957968, tv_nsec = 822132595}, st_ctim = {tv_sec = 1779957968, tv_nsec = 822132595}, __glibc_reserved = {0, 0, 0}}
        data = 0x15149548
        pkgid = ">\000\000\000\000\000\000\000`h\353\206\000\000\000"
        leadsigid = "\001\032\000\000\000\000\000\000\200p\036\300\033\177\000"
        hdrid = "\223\207(\371{Տj'\025\n\334\n\236xR\310\357W\300\376\177\000\0009\022S\300\033\177\000"
        pkgidtype = 0
        leadsigidtype = 0
        hdridtype = 47
        chksumtype = 49
        chksumh = 0x1520b670
        leadsigchksumh = 0x0
#2  0x00007f1bc00394e1 in dnf_sack_add_cmdline_package_flags (sack=0x15190950 [DnfSack], fn=0x15322410 "/tmp/hawkeyxoe3yS/null.rpm", flags=40963)
    at ../../libdnf/dnf-sack.cpp:1274
        priv = 0x151908a0
        repo = 0x15222460
        p = 0
        hrepo = 0xfbad2404
#3  0x00007f1bc003958e in dnf_sack_add_cmdline_package (sack=0x15190950 [DnfSack], fn=0x15322410 "/tmp/hawkeyxoe3yS/null.rpm")
    at ../../libdnf/dnf-sack.cpp:1300
#4  0x000000000041f2e7 in test_add_cmdline_package_fn (_i=0) at ../../../tests/hawkey/test_sack.cpp:171
        sack = 0x15190950
        path_mystery = 0x15190c80 "/home/mblaha/src/libdnf/data/tests/hawkey/yum/mystery-devel-19.67-1.noarch.rpm"
        pkg_mystery = 0x1531ed30
        location_mystery = 0x15308380 "/home/mblaha/src/libdnf/data/tests/hawkey/yum/mystery-devel-19.67-1.noarch.rpm"
        path_tour = 0x15305af0 "/home/mblaha/src/libdnf/data/tests/hawkey/yum/tour-4-6.noarch.rpm"
        pkg_tour = 0x15193000
        location_tour = 0x152d8b90 "/home/mblaha/src/libdnf/data/tests/hawkey/yum/tour-4-6.noarch.rpm"
        path_null_rpm = 0x15322410 "/tmp/hawkeyxoe3yS/null.rpm"
        fp = 0x151f74d0
#5  0x00007f1bc04f42d1 in tcase_run_tfun_fork (sr=<optimized out>, tc=<optimized out>, tfun=<optimized out>, i=0)
    at /usr/src/debug/check-0.15.2-19.fc43.x86_64/src/check_run.c:497
        tr = <optimized out>
        pid_w = <optimized out>
        pid = <optimized out>
        status = 0
        ts_start = {tv_sec = 422474, tv_nsec = 693916613}
        ts_end = {tv_sec = 0, tv_nsec = 0}
        timerid = 0xb
        timer_spec = {it_interval = {tv_sec = 0, tv_nsec = 0}, it_value = {tv_sec = 4, tv_nsec = 0}}
#6  srunner_iterate_tcase_tfuns (sr=<optimized out>, tc=0x15184910) at /usr/src/debug/check-0.15.2-19.fc43.x86_64/src/check_run.c:256
        i = 0
        tfl = 0x151871c0
        tfun = 0x15186ea0
        tr = <optimized out>
#7  srunner_run_tcase (sr=0x15188f30, tc=0x15184910) at /usr/src/debug/check-0.15.2-19.fc43.x86_64/src/check_run.c:402
#8  srunner_iterate_suites (print_mode=<optimized out>, sr=0x15188f30, sname=0x0, tcname=0x0, include_tags=0x0, exclude_tags=0x0)
    at /usr/src/debug/check-0.15.2-19.fc43.x86_64/src/check_run.c:222
        s = <optimized out>
        include_tag_lst = 0x151900b0
        exclude_tag_lst = 0x151900f0
        slst = <optimized out>
        tcl = <optimized out>
        tc = 0x15184910
#9  srunner_run_tagged (sr=0x15188f30, sname=0x0, tcname=0x0, include_tags=0x0, exclude_tags=0x0, print_mode=<optimized out>)
    at /usr/src/debug/check-0.15.2-19.fc43.x86_64/src/check_run.c:814
        sigalarm_new_action = {__sigaction_handler = {sa_handler = 0x7f1bc04f0b00 <sig_handler>, sa_sigaction = 0x7f1bc04f0b00 <sig_handler>}, sa_mask = {__val = {0 <repeats 16 times>}}, sa_flags = 0, sa_restorer = 0x0}
        sigalarm_old_action = {__sigaction_handler = {sa_handler = 0x0, sa_sigaction = 0x0}, sa_mask = {__val = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139757147564195, 0, 2, 140732501496152, 1, 139757167702016}}, sa_flags = 0, sa_restorer = 0x0}
        sigint_new_action = {__sigaction_handler = {sa_handler = 0x7f1bc04f0b00 <sig_handler>, sa_sigaction = 0x7f1bc04f0b00 <sig_handler>}, sa_mask = {__val = {0 <repeats 16 times>}}, sa_flags = 0, sa_restorer = 0x0}
        sigterm_new_action = {__sigaction_handler = {sa_handler = 0x7f1bc04f0b00 <sig_handler>, sa_sigaction = 0x7f1bc04f0b00 <sig_handler>}, sa_mask = {__val = {0 <repeats 16 times>}}, sa_flags = 0, sa_restorer = 0x0}
#10 0x0000000000411d04 in main (argc=1, argv=0x7ffed6c29158) at ../../../tests/hawkey/test_main.cpp:84
        number_failed = 32539
        sr = 0x15188f30

Commit a4f1b2f ("Split the checksum implementation into chksum_impl.c")
introduced a NULL pointer dereference in solv_chksum_free(). The
refactoring added an else branch that accesses chk->impl to free
internal resources, but this branch is reached even when chk is NULL.

Before the refactoring, solv_chksum_free(NULL, NULL) was safe:
  - the "if (cp)" branch was skipped (cp is NULL)
  - solv_free(NULL) was called, which is a no-op

After the refactoring:
  - the "if (cp)" branch is skipped
  - the new "else if (chk->impl)" dereferences chk, which is NULL

Fix by adding a NULL check for chk at the top of solv_chksum_free(),
restoring the pre-refactoring behavior.

Signed-off-by: Marek Blaha <mblaha@redhat.com>
@mlschroe mlschroe merged commit dc2d46c into openSUSE:master May 28, 2026
1 check passed
@mlschroe

Copy link
Copy Markdown
Member

Thanks!

@mlschroe

Copy link
Copy Markdown
Member

Fixed in libsolv-0.7.39

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants