Uploaded image for project: 'RHEL'
  1. RHEL
  2. RHEL-35249

librpm crashes when applying the upgrade transaction from RHEL7 to RHEL8

    • Icon: Bug Bug
    • Resolution: Done-Errata
    • Icon: Major Major
    • rhel-9.5
    • rhel-8.9.0
    • rpm
    • rpm-4.16.1.3-30.el9
    • None
    • Important
    • rhel-sst-cs-software-management
    • ssg_core_services
    • 15
    • 17
    • None
    • False
    • Hide

      None

      Show
      None
    • None
    • Red Hat Enterprise Linux
    • None
    • Hide

      AC: SanityOnly aka RegressionOnly. Patch applied correctly. Existing tests are passing.

      Show
      AC: SanityOnly aka RegressionOnly. Patch applied correctly. Existing tests are passing.
    • Pass
    • Not Needed
    • RegressionOnly
    • Release Note Not Required
    • All
    • None

      What were you trying to do that didn't work?

      A customer is trying to upgrade a system from RHEL7 to RHEL8. All goes fine until he reboots on the RHEL8 kernel to perform the effective upgrade. He can then see a segfault on librpm:

      [ 4845.265663] dnf[4909]: segfault at 0 ip 00007fe81667ba5c sp 00007ffff23e4ce0 error 4 in librpm.so.8.2.0[7fe81661f000+78000]
      

      The segfault above (which is a NULL pointer dereference) occurs when filesystem package gets installed, at trigger step:

      Running transaction
      RPMDB altered outside of DNF.
        Running scriptlet: filesystem-3.8-6.el8.x86_64                                                                  1/1 
        Preparing        :                                                                                              1/1 
      Segmentation fault
      

      I can reproduce this at will with customer's RPMDB (will be attached to another Jira).
      Checking the coredump, we can see that runFileTriggers() crashes due to dereferencing NULL pointer on line 544:

      Program terminated with signal SIGSEGV, Segmentation fault.
      #0  0x00007ff35f4a0a5c in runFileTriggers (ts=ts@entry=0x55f9df06bb10, te=te@entry=0x0, sense=sense@entry=131072, 
          tm=tm@entry=4, priorityClass=priorityClass@entry=0) at rpmtriggers.c:544
      544            priority = *rpmtdGetUint32(&priorities);
      
      171 uint32_t * rpmtdGetUint32(rpmtd td)
      172 {
      173     uint32_t *res = NULL;
      174 
      175     if (td != NULL && td->type == RPM_INT32_TYPE) {
      176         int ix = (td->ix >= 0 ? td->ix : 0);
      177         res = (uint32_t *) td->data + ix;
      178     }
      179     return res;
      180 }
      
      (gdb) p priorities
      $2 = {tag = 5085, type = 0, count = 0, data = 0x0, flags = 0, ix = -1, size = 0}
      
      432 typedef enum rpmTagType_e {
      433 #define RPM_MIN_TYPE            0
      434     RPM_NULL_TYPE               =  0,
      435     RPM_CHAR_TYPE               =  1,
      436     RPM_INT8_TYPE               =  2,
      437     RPM_INT16_TYPE              =  3,
      438     RPM_INT32_TYPE              =  4,
       :
      
      362     RPMTAG_TRANSFILETRIGGERPRIORITIES   = 5085, /* i[] */
      

      The NULL point dereference occurs because function rpmtdGetUint32() returned NULL, because priorities->type is 0, hence doesn't match expected value 4.

      The trigger is apparently on file /etc/systemd/system, but it's unclear to me where this trigger comes from:

      (gdb) p (char *)key
      $6 = 0x55f9dca56fb0 "/etc/systemd/system"
      
      492 rpmRC runFileTriggers(rpmts ts, rpmte te, rpmsenseFlags sense,
      493                         rpmscriptTriggerModes tm, int priorityClass)
      494 {
       :
      522         /* Check if file trigger is fired by any file in ts/te */
      523         if (matchFunc(ts, te, pfx, sense)) {
      524             for (i = 0; i < rpmdbIndexIteratorNumPkgs(ii); i++) {
       :
      540                 /* Get priority of trigger from header */
      541                 trigH = rpmdbGetHeaderAt(rpmtsGetRdb(ts), offset);
      542                 headerGet(trigH, priorityTag, &priorities, HEADERGET_MINMEM);
      543                 rpmtdSetIndex(&priorities, tix);
      544                 priority = *rpmtdGetUint32(&priorities);
       :
      

      Here above we can see the condition matched on line 523, but then it seems that headerGet() on line 542 must have failed somehow, but since the return code is not checked, this leads to crashing on line 544.

      Please provide the package NVR for which bug is seen:

      rpm-libs-4.14.3-28.el8_9.x86_64

      How reproducible:

      Always

      Steps to reproduce

      1. Install a RHEL7 system and fully upgrade it, ready to leapp it
      2. Install customer's RPMDB on /var/lib/rpm
      3. Create /etc/mail if directory doesn't exist (this is needed depending on how you installed the system)
      4. Execute leapp preupgrade, fix the inhibitors then execute leapp upgrade
      5. Don't reboot but enter the container that would execute the transaction
         # systemd-nspawn --register=no -D /var/lib/leapp/el8userspace --bind=/:/installroot --bind=/dev:/installroot/dev --bind=/proc:/installroot/proc --bind=/run/udev:/installroot/run/udev --bind=/sys:/installroot/sys --bind=/boot:/installroot/boot --bind=/boot:/installroot/boot --setenv=LEAPP_UPGRADE_PATH_TARGET_RELEASE=8.9 --setenv=LEAPP_NO_RHSM=1 --setenv=LEAPP_EXPERIMENTAL=0 --setenv=LEAPP_UPGRADE_PATH_FLAVOUR=default --setenv=LEAPP_COMMON_TOOLS=:/etc/leapp/repos.d/system_upgrade/common/tools:/etc/leapp/repos.d/system_upgrade/el7toel8/tools --setenv=LEAPP_NO_RHSM_FACTS=1 --setenv=LEAPP_COMMON_FILES=:/etc/leapp/repos.d/system_upgrade/common/files:/etc/leapp/repos.d/system_upgrade/el7toel8/files --setenv=LEAPP_IPU_IN_PROGRESS=7to8 --setenv=LEAPP_UNSUPPORTED=0 --setenv=LEAPP_EXECUTION_ID=9d70457f-1521-4c0f-b4d4-3a1bbea9ac63 --setenv=LEAPP_HOSTNAME=vm-leapp7.libvirt
         
      6. Inside the container, make sure you can get coredumps then execute the DNF transaction
         # ulimit -c unlimited
         # dnf rhel-upgrade upgrade /var/lib/leapp/dnf-plugin-data.txt -v --disableplugin subscription-manager
         

      Note that the DNF transaction will break /var/lib/rpm on the RHEL7 system.

      Expected results

      Upgrade of packages

      Actual results

      Core dump

              mdomonko@redhat.com Michal Domonkos
              rhn-support-rmetrich Renaud Métrich
              packaging-team-maint packaging-team-maint
              Jan Blazek Jan Blazek
              Votes:
              1 Vote for this issue
              Watchers:
              8 Start watching this issue

                Created:
                Updated:
                Resolved: