diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d13e7f5 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/rpm-4.16.1.3.tar.bz2 diff --git a/.rpm.metadata b/.rpm.metadata new file mode 100644 index 0000000..ec701c1 --- /dev/null +++ b/.rpm.metadata @@ -0,0 +1 @@ +4c70c0dc08aec5ba29f3ee72eda774bd32230f77 SOURCES/rpm-4.16.1.3.tar.bz2 diff --git a/SOURCES/0001-Issue-deprecation-warning-when-creating-BDB-database.patch b/SOURCES/0001-Issue-deprecation-warning-when-creating-BDB-database.patch new file mode 100644 index 0000000..94484d6 --- /dev/null +++ b/SOURCES/0001-Issue-deprecation-warning-when-creating-BDB-database.patch @@ -0,0 +1,28 @@ +From 5a80033676f331de2b0979fe7be9557279b6bff3 Mon Sep 17 00:00:00 2001 +Message-Id: <5a80033676f331de2b0979fe7be9557279b6bff3.1603865959.git.pmatilai@redhat.com> +From: Panu Matilainen +Date: Wed, 28 Oct 2020 08:14:55 +0200 +Subject: [PATCH] Issue deprecation warning when creating BDB databases + +--- + lib/backend/db3.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/lib/backend/db3.c b/lib/backend/db3.c +index 68cfa6fb2..cb31676e7 100644 +--- a/lib/backend/db3.c ++++ b/lib/backend/db3.c +@@ -874,6 +874,10 @@ static int db3_dbiOpen(rpmdb rdb, rpmDbiTagVal rpmtag, dbiIndex * dbip, int flag + oflags &= ~DB_RDONLY; + dbtype = (rpmtag == RPMDBI_PACKAGES) ? DB_HASH : DB_BTREE; + retry_open--; ++ if (rpmtag == RPMDBI_PACKAGES) { ++ rpmlog(RPMLOG_WARNING, ++ "using deprecated bdb database backend"); ++ } + } else { + retry_open = 0; + } +-- +2.28.0 + diff --git a/SOURCES/0001-NFC-debugedit-Protect-macro-arguments-by-parentheses.patch b/SOURCES/0001-NFC-debugedit-Protect-macro-arguments-by-parentheses.patch new file mode 100644 index 0000000..6607373 --- /dev/null +++ b/SOURCES/0001-NFC-debugedit-Protect-macro-arguments-by-parentheses.patch @@ -0,0 +1,61 @@ +From a93b0f5c9f0abef6efb5413df9e98b047a2a9a46 Mon Sep 17 00:00:00 2001 +From: Jan Kratochvil +Date: Mon, 17 Aug 2020 16:56:56 +0200 +Subject: [PATCH 1/6] [NFC] debugedit: Protect macro arguments by parentheses + +--- + tools/debugedit.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/tools/debugedit.c b/tools/debugedit.c +index 6bea88551..a351adec8 100644 +--- a/tools/debugedit.c ++++ b/tools/debugedit.c +@@ -233,7 +233,7 @@ typedef struct + int shift = 0; \ + do \ + { \ +- c = *ptr++; \ ++ c = *(ptr)++; \ + ret |= (c & 0x7f) << shift; \ + shift += 7; \ + } while (c & 0x80); \ +@@ -251,7 +251,7 @@ typedef struct + valv >>= 7; \ + if (valv) \ + c |= 0x80; \ +- *ptr++ = c; \ ++ *(ptr)++ = c; \ + } \ + while (valv); \ + }) +@@ -311,7 +311,7 @@ strptr (DSO *dso, int sec, off_t offset) + } + + +-#define read_8(ptr) *ptr++ ++#define read_8(ptr) *(ptr)++ + + #define read_16(ptr) ({ \ + uint16_t ret = do_read_16 (ptr); \ +@@ -328,13 +328,13 @@ strptr (DSO *dso, int sec, off_t offset) + REL *relptr, *relend; + int reltype; + +-#define do_read_32_relocated(ptr) ({ \ +- uint32_t dret = do_read_32 (ptr); \ ++#define do_read_32_relocated(xptr) ({ \ ++ uint32_t dret = do_read_32 (xptr); \ + if (relptr) \ + { \ +- while (relptr < relend && relptr->ptr < ptr) \ ++ while (relptr < relend && relptr->ptr < (xptr)) \ + ++relptr; \ +- if (relptr < relend && relptr->ptr == ptr) \ ++ if (relptr < relend && relptr->ptr == (xptr)) \ + { \ + if (reltype == SHT_REL) \ + dret += relptr->addend; \ +-- +2.18.4 + diff --git a/SOURCES/0001-find-debuginfo.sh-decompress-DWARF-compressed-ELF-se.patch b/SOURCES/0001-find-debuginfo.sh-decompress-DWARF-compressed-ELF-se.patch new file mode 100644 index 0000000..ee4b7cf --- /dev/null +++ b/SOURCES/0001-find-debuginfo.sh-decompress-DWARF-compressed-ELF-se.patch @@ -0,0 +1,30 @@ +From f2bc669cd0a080792522dd1bb7f50ef7025f16f0 Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Sat, 21 Jul 2018 10:13:04 +0200 +Subject: [PATCH] find-debuginfo.sh: decompress DWARF compressed ELF sections + +debugedit and dwz do not support DWARF compressed ELF sections, let's +just decompress those before extracting debuginfo. + +Tested-by: Igor Gnatenko +--- + scripts/find-debuginfo.sh | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/scripts/find-debuginfo.sh b/scripts/find-debuginfo.sh +index 90a44942d..7b01bc036 100755 +--- a/scripts/find-debuginfo.sh ++++ b/scripts/find-debuginfo.sh +@@ -357,6 +357,9 @@ do_file() + get_debugfn "$f" + [ -f "${debugfn}" ] && return + ++ echo "explicitly decompress any DWARF compressed ELF sections in $f" ++ eu-elfcompress -q -p -t none "$f" ++ + echo "extracting debug info from $f" + # See also cpio SOURCEFILE copy. Directories must match up. + debug_base_name="$RPM_BUILD_DIR" +-- +2.18.0 + diff --git a/SOURCES/0002-NFC-debugedit-Move-code-from-edit_dwarf2-to-edit_inf.patch b/SOURCES/0002-NFC-debugedit-Move-code-from-edit_dwarf2-to-edit_inf.patch new file mode 100644 index 0000000..74c37f7 --- /dev/null +++ b/SOURCES/0002-NFC-debugedit-Move-code-from-edit_dwarf2-to-edit_inf.patch @@ -0,0 +1,753 @@ +From de119ea9797f3ccfa3842e3926b6ea8198607207 Mon Sep 17 00:00:00 2001 +From: Jan Kratochvil +Date: Sat, 1 Aug 2020 10:43:12 +0200 +Subject: [PATCH 2/6] [NFC] debugedit: Move code from edit_dwarf2() to + edit_info(). + +--- + tools/debugedit.c | 672 +++++++++++++++++++++++----------------------- + 1 file changed, 343 insertions(+), 329 deletions(-) + +diff --git a/tools/debugedit.c b/tools/debugedit.c +index a351adec8..cad0cc349 100644 +--- a/tools/debugedit.c ++++ b/tools/debugedit.c +@@ -1964,6 +1964,106 @@ line_rel_cmp (const void *a, const void *b) + return 0; + } + ++static int ++edit_info (DSO *dso, int phase) ++{ ++ unsigned char *ptr, *endcu, *endsec; ++ uint32_t value; ++ htab_t abbrev; ++ struct abbrev_tag tag, *t; ++ ++ ptr = debug_sections[DEBUG_INFO].data; ++ setup_relbuf(dso, &debug_sections[DEBUG_INFO], &reltype); ++ endsec = ptr + debug_sections[DEBUG_INFO].size; ++ while (ptr < endsec) ++ { ++ if (ptr + 11 > endsec) ++ { ++ error (0, 0, "%s: .debug_info CU header too small", ++ dso->filename); ++ return 1; ++ } ++ ++ endcu = ptr + 4; ++ endcu += read_32 (ptr); ++ if (endcu == ptr + 0xffffffff) ++ { ++ error (0, 0, "%s: 64-bit DWARF not supported", dso->filename); ++ return 1; ++ } ++ ++ if (endcu > endsec) ++ { ++ error (0, 0, "%s: .debug_info too small", dso->filename); ++ return 1; ++ } ++ ++ cu_version = read_16 (ptr); ++ if (cu_version != 2 && cu_version != 3 && cu_version != 4) ++ { ++ error (0, 0, "%s: DWARF version %d unhandled", dso->filename, ++ cu_version); ++ return 1; ++ } ++ ++ value = read_32_relocated (ptr); ++ if (value >= debug_sections[DEBUG_ABBREV].size) ++ { ++ if (debug_sections[DEBUG_ABBREV].data == NULL) ++ error (0, 0, "%s: .debug_abbrev not present", dso->filename); ++ else ++ error (0, 0, "%s: DWARF CU abbrev offset too large", ++ dso->filename); ++ return 1; ++ } ++ ++ if (ptr_size == 0) ++ { ++ ptr_size = read_8 (ptr); ++ if (ptr_size != 4 && ptr_size != 8) ++ { ++ error (0, 0, "%s: Invalid DWARF pointer size %d", ++ dso->filename, ptr_size); ++ return 1; ++ } ++ } ++ else if (read_8 (ptr) != ptr_size) ++ { ++ error (0, 0, "%s: DWARF pointer size differs between CUs", ++ dso->filename); ++ return 1; ++ } ++ ++ abbrev = read_abbrev (dso, ++ debug_sections[DEBUG_ABBREV].data + value); ++ if (abbrev == NULL) ++ return 1; ++ ++ while (ptr < endcu) ++ { ++ tag.entry = read_uleb128 (ptr); ++ if (tag.entry == 0) ++ continue; ++ t = htab_find_with_hash (abbrev, &tag, tag.entry); ++ if (t == NULL) ++ { ++ error (0, 0, "%s: Could not find DWARF abbreviation %d", ++ dso->filename, tag.entry); ++ htab_delete (abbrev); ++ return 1; ++ } ++ ++ ptr = edit_attributes (dso, ptr, t, phase); ++ if (ptr == NULL) ++ break; ++ } ++ ++ htab_delete (abbrev); ++ } ++ ++ return 0; ++} ++ + static int + edit_dwarf2 (DSO *dso) + { +@@ -2100,385 +2200,299 @@ edit_dwarf2 (DSO *dso) + return 1; + } + +- if (debug_sections[DEBUG_INFO].data != NULL) ++ if (debug_sections[DEBUG_INFO].data == NULL) ++ return 0; ++ ++ unsigned char *ptr, *endcu, *endsec; ++ uint32_t value; ++ htab_t abbrev; ++ struct abbrev_tag tag, *t; ++ int phase; ++ bool info_rel_updated = false; ++ bool macro_rel_updated = false; ++ ++ for (phase = 0; phase < 2; phase++) + { +- unsigned char *ptr, *endcu, *endsec; +- uint32_t value; +- htab_t abbrev; +- struct abbrev_tag tag, *t; +- int phase; +- bool info_rel_updated = false; +- bool macro_rel_updated = false; ++ /* If we don't need to update anyhing, skip phase 1. */ ++ if (phase == 1 ++ && !need_strp_update ++ && !need_string_replacement ++ && !need_stmt_update) ++ break; + +- for (phase = 0; phase < 2; phase++) ++ rel_updated = false; ++ if (edit_info (dso, phase)) ++ return 1; ++ ++ /* Remember whether any .debug_info relocations might need ++ to be updated. */ ++ info_rel_updated = rel_updated; ++ ++ /* We might have to recalculate/rewrite the debug_line ++ section. We need to do that before going into phase one ++ so we have all new offsets. We do this separately from ++ scanning the dirs/file names because the DW_AT_stmt_lists ++ might not be in order or skip some padding we might have ++ to (re)move. */ ++ if (phase == 0 && need_stmt_update) + { +- /* If we don't need to update anyhing, skip phase 1. */ +- if (phase == 1 +- && !need_strp_update +- && !need_string_replacement +- && !need_stmt_update) +- break; ++ edit_dwarf2_line (dso); + +- ptr = debug_sections[DEBUG_INFO].data; +- setup_relbuf(dso, &debug_sections[DEBUG_INFO], &reltype); +- rel_updated = false; +- endsec = ptr + debug_sections[DEBUG_INFO].size; +- while (ptr < endsec) ++ /* The line table programs will be moved ++ forward/backwards a bit in the new data. Update the ++ debug_line relocations to the new offsets. */ ++ int rndx = debug_sections[DEBUG_LINE].relsec; ++ if (rndx != 0) + { +- if (ptr + 11 > endsec) +- { +- error (0, 0, "%s: .debug_info CU header too small", +- dso->filename); +- return 1; +- } +- +- endcu = ptr + 4; +- endcu += read_32 (ptr); +- if (endcu == ptr + 0xffffffff) +- { +- error (0, 0, "%s: 64-bit DWARF not supported", dso->filename); +- return 1; +- } +- +- if (endcu > endsec) +- { +- error (0, 0, "%s: .debug_info too small", dso->filename); +- return 1; +- } +- +- cu_version = read_16 (ptr); +- if (cu_version != 2 && cu_version != 3 && cu_version != 4) +- { +- error (0, 0, "%s: DWARF version %d unhandled", dso->filename, +- cu_version); +- return 1; +- } +- +- value = read_32_relocated (ptr); +- if (value >= debug_sections[DEBUG_ABBREV].size) ++ LINE_REL *rbuf; ++ size_t rels; ++ Elf_Data *rdata = elf_getdata (dso->scn[rndx], NULL); ++ int rtype = dso->shdr[rndx].sh_type; ++ rels = dso->shdr[rndx].sh_size / dso->shdr[rndx].sh_entsize; ++ rbuf = malloc (rels * sizeof (LINE_REL)); ++ if (rbuf == NULL) ++ error (1, errno, "%s: Could not allocate line relocations", ++ dso->filename); ++ ++ /* Sort them by offset into section. */ ++ for (size_t i = 0; i < rels; i++) + { +- if (debug_sections[DEBUG_ABBREV].data == NULL) +- error (0, 0, "%s: .debug_abbrev not present", dso->filename); ++ if (rtype == SHT_RELA) ++ { ++ GElf_Rela rela; ++ if (gelf_getrela (rdata, i, &rela) == NULL) ++ error (1, 0, "Couldn't get relocation: %s", ++ elf_errmsg (-1)); ++ rbuf[i].r_offset = rela.r_offset; ++ rbuf[i].ndx = i; ++ } + else +- error (0, 0, "%s: DWARF CU abbrev offset too large", +- dso->filename); +- return 1; +- } +- +- if (ptr_size == 0) +- { +- ptr_size = read_8 (ptr); +- if (ptr_size != 4 && ptr_size != 8) + { +- error (0, 0, "%s: Invalid DWARF pointer size %d", +- dso->filename, ptr_size); +- return 1; ++ GElf_Rel rel; ++ if (gelf_getrel (rdata, i, &rel) == NULL) ++ error (1, 0, "Couldn't get relocation: %s", ++ elf_errmsg (-1)); ++ rbuf[i].r_offset = rel.r_offset; ++ rbuf[i].ndx = i; + } + } +- else if (read_8 (ptr) != ptr_size) +- { +- error (0, 0, "%s: DWARF pointer size differs between CUs", +- dso->filename); +- return 1; +- } ++ qsort (rbuf, rels, sizeof (LINE_REL), line_rel_cmp); + +- abbrev = read_abbrev (dso, +- debug_sections[DEBUG_ABBREV].data + value); +- if (abbrev == NULL) +- return 1; +- +- while (ptr < endcu) ++ size_t lndx = 0; ++ for (size_t i = 0; i < rels; i++) + { +- tag.entry = read_uleb128 (ptr); +- if (tag.entry == 0) +- continue; +- t = htab_find_with_hash (abbrev, &tag, tag.entry); +- if (t == NULL) ++ /* These relocations only happen in ET_REL files ++ and are section offsets. */ ++ GElf_Addr r_offset; ++ size_t ndx = rbuf[i].ndx; ++ ++ GElf_Rel rel; ++ GElf_Rela rela; ++ if (rtype == SHT_RELA) + { +- error (0, 0, "%s: Could not find DWARF abbreviation %d", +- dso->filename, tag.entry); +- htab_delete (abbrev); +- return 1; ++ if (gelf_getrela (rdata, ndx, &rela) == NULL) ++ error (1, 0, "Couldn't get relocation: %s", ++ elf_errmsg (-1)); ++ r_offset = rela.r_offset; ++ } ++ else ++ { ++ if (gelf_getrel (rdata, ndx, &rel) == NULL) ++ error (1, 0, "Couldn't get relocation: %s", ++ elf_errmsg (-1)); ++ r_offset = rel.r_offset; + } + +- ptr = edit_attributes (dso, ptr, t, phase); +- if (ptr == NULL) +- break; +- } ++ while (lndx < dso->lines.used ++ && r_offset > (dso->lines.table[lndx].old_idx ++ + 4 ++ + dso->lines.table[lndx].unit_length)) ++ lndx++; + +- htab_delete (abbrev); +- } ++ if (lndx >= dso->lines.used) ++ error (1, 0, ++ ".debug_line relocation offset out of range"); + +- /* Remember whether any .debug_info relocations might need +- to be updated. */ +- info_rel_updated = rel_updated; +- +- /* We might have to recalculate/rewrite the debug_line +- section. We need to do that before going into phase one +- so we have all new offsets. We do this separately from +- scanning the dirs/file names because the DW_AT_stmt_lists +- might not be in order or skip some padding we might have +- to (re)move. */ +- if (phase == 0 && need_stmt_update) +- { +- edit_dwarf2_line (dso); ++ /* Offset (pointing into the line program) moves ++ from old to new index including the header ++ size diff. */ ++ r_offset += (ssize_t)((dso->lines.table[lndx].new_idx ++ - dso->lines.table[lndx].old_idx) ++ + dso->lines.table[lndx].size_diff); + +- /* The line table programs will be moved +- forward/backwards a bit in the new data. Update the +- debug_line relocations to the new offsets. */ +- int rndx = debug_sections[DEBUG_LINE].relsec; +- if (rndx != 0) +- { +- LINE_REL *rbuf; +- size_t rels; +- Elf_Data *rdata = elf_getdata (dso->scn[rndx], NULL); +- int rtype = dso->shdr[rndx].sh_type; +- rels = dso->shdr[rndx].sh_size / dso->shdr[rndx].sh_entsize; +- rbuf = malloc (rels * sizeof (LINE_REL)); +- if (rbuf == NULL) +- error (1, errno, "%s: Could not allocate line relocations", +- dso->filename); +- +- /* Sort them by offset into section. */ +- for (size_t i = 0; i < rels; i++) ++ if (rtype == SHT_RELA) + { +- if (rtype == SHT_RELA) +- { +- GElf_Rela rela; +- if (gelf_getrela (rdata, i, &rela) == NULL) +- error (1, 0, "Couldn't get relocation: %s", +- elf_errmsg (-1)); +- rbuf[i].r_offset = rela.r_offset; +- rbuf[i].ndx = i; +- } +- else +- { +- GElf_Rel rel; +- if (gelf_getrel (rdata, i, &rel) == NULL) +- error (1, 0, "Couldn't get relocation: %s", +- elf_errmsg (-1)); +- rbuf[i].r_offset = rel.r_offset; +- rbuf[i].ndx = i; +- } ++ rela.r_offset = r_offset; ++ if (gelf_update_rela (rdata, ndx, &rela) == 0) ++ error (1, 0, "Couldn't update relocation: %s", ++ elf_errmsg (-1)); + } +- qsort (rbuf, rels, sizeof (LINE_REL), line_rel_cmp); +- +- size_t lndx = 0; +- for (size_t i = 0; i < rels; i++) ++ else + { +- /* These relocations only happen in ET_REL files +- and are section offsets. */ +- GElf_Addr r_offset; +- size_t ndx = rbuf[i].ndx; +- +- GElf_Rel rel; +- GElf_Rela rela; +- if (rtype == SHT_RELA) +- { +- if (gelf_getrela (rdata, ndx, &rela) == NULL) +- error (1, 0, "Couldn't get relocation: %s", +- elf_errmsg (-1)); +- r_offset = rela.r_offset; +- } +- else +- { +- if (gelf_getrel (rdata, ndx, &rel) == NULL) +- error (1, 0, "Couldn't get relocation: %s", +- elf_errmsg (-1)); +- r_offset = rel.r_offset; +- } +- +- while (lndx < dso->lines.used +- && r_offset > (dso->lines.table[lndx].old_idx +- + 4 +- + dso->lines.table[lndx].unit_length)) +- lndx++; +- +- if (lndx >= dso->lines.used) +- error (1, 0, +- ".debug_line relocation offset out of range"); +- +- /* Offset (pointing into the line program) moves +- from old to new index including the header +- size diff. */ +- r_offset += (ssize_t)((dso->lines.table[lndx].new_idx +- - dso->lines.table[lndx].old_idx) +- + dso->lines.table[lndx].size_diff); +- +- if (rtype == SHT_RELA) +- { +- rela.r_offset = r_offset; +- if (gelf_update_rela (rdata, ndx, &rela) == 0) +- error (1, 0, "Couldn't update relocation: %s", +- elf_errmsg (-1)); +- } +- else +- { +- rel.r_offset = r_offset; +- if (gelf_update_rel (rdata, ndx, &rel) == 0) +- error (1, 0, "Couldn't update relocation: %s", +- elf_errmsg (-1)); +- } ++ rel.r_offset = r_offset; ++ if (gelf_update_rel (rdata, ndx, &rel) == 0) ++ error (1, 0, "Couldn't update relocation: %s", ++ elf_errmsg (-1)); + } +- +- elf_flagdata (rdata, ELF_C_SET, ELF_F_DIRTY); +- free (rbuf); + } ++ ++ elf_flagdata (rdata, ELF_C_SET, ELF_F_DIRTY); ++ free (rbuf); + } ++ } + +- /* The .debug_macro section also contains offsets into the +- .debug_str section and references to the .debug_line +- tables, so we need to update those as well if we update +- the strings or the stmts. */ +- if ((need_strp_update || need_stmt_update) +- && debug_sections[DEBUG_MACRO].data) ++ /* The .debug_macro section also contains offsets into the ++ .debug_str section and references to the .debug_line ++ tables, so we need to update those as well if we update ++ the strings or the stmts. */ ++ if ((need_strp_update || need_stmt_update) ++ && debug_sections[DEBUG_MACRO].data) ++ { ++ /* There might be multiple (COMDAT) .debug_macro sections. */ ++ struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO]; ++ while (macro_sec != NULL) + { +- /* There might be multiple (COMDAT) .debug_macro sections. */ +- struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO]; +- while (macro_sec != NULL) +- { +- setup_relbuf(dso, macro_sec, &reltype); +- rel_updated = false; ++ setup_relbuf(dso, macro_sec, &reltype); ++ rel_updated = false; + +- ptr = macro_sec->data; +- endsec = ptr + macro_sec->size; +- int op = 0, macro_version, macro_flags; +- int offset_len = 4, line_offset = 0; ++ ptr = macro_sec->data; ++ endsec = ptr + macro_sec->size; ++ int op = 0, macro_version, macro_flags; ++ int offset_len = 4, line_offset = 0; + +- while (ptr < endsec) ++ while (ptr < endsec) ++ { ++ if (!op) + { +- if (!op) +- { +- macro_version = read_16 (ptr); +- macro_flags = read_8 (ptr); +- if (macro_version < 4 || macro_version > 5) +- error (1, 0, "unhandled .debug_macro version: %d", +- macro_version); +- if ((macro_flags & ~2) != 0) +- error (1, 0, "unhandled .debug_macro flags: 0x%x", +- macro_flags); +- +- offset_len = (macro_flags & 0x01) ? 8 : 4; +- line_offset = (macro_flags & 0x02) ? 1 : 0; +- +- if (offset_len != 4) +- error (0, 1, +- "Cannot handle 8 byte macro offsets: %s", +- dso->filename); +- +- /* Update the line_offset if it is there. */ +- if (line_offset) +- { +- if (phase == 0) +- ptr += offset_len; +- else +- { +- size_t idx, new_idx; +- idx = do_read_32_relocated (ptr); +- new_idx = find_new_list_offs (&dso->lines, +- idx); +- write_32_relocated (ptr, new_idx); +- } +- } +- } ++ macro_version = read_16 (ptr); ++ macro_flags = read_8 (ptr); ++ if (macro_version < 4 || macro_version > 5) ++ error (1, 0, "unhandled .debug_macro version: %d", ++ macro_version); ++ if ((macro_flags & ~2) != 0) ++ error (1, 0, "unhandled .debug_macro flags: 0x%x", ++ macro_flags); ++ ++ offset_len = (macro_flags & 0x01) ? 8 : 4; ++ line_offset = (macro_flags & 0x02) ? 1 : 0; ++ ++ if (offset_len != 4) ++ error (0, 1, ++ "Cannot handle 8 byte macro offsets: %s", ++ dso->filename); + +- op = read_8 (ptr); +- if (!op) +- continue; +- switch(op) ++ /* Update the line_offset if it is there. */ ++ if (line_offset) + { +- case DW_MACRO_GNU_define: +- case DW_MACRO_GNU_undef: +- read_uleb128 (ptr); +- ptr = ((unsigned char *) strchr ((char *) ptr, '\0') +- + 1); +- break; +- case DW_MACRO_GNU_start_file: +- read_uleb128 (ptr); +- read_uleb128 (ptr); +- break; +- case DW_MACRO_GNU_end_file: +- break; +- case DW_MACRO_GNU_define_indirect: +- case DW_MACRO_GNU_undef_indirect: +- read_uleb128 (ptr); + if (phase == 0) +- { +- size_t idx = read_32_relocated (ptr); +- record_existing_string_entry_idx (&dso->strings, +- idx); +- } ++ ptr += offset_len; + else + { +- struct stridxentry *entry; + size_t idx, new_idx; + idx = do_read_32_relocated (ptr); +- entry = string_find_entry (&dso->strings, idx); +- new_idx = strent_offset (entry->entry); ++ new_idx = find_new_list_offs (&dso->lines, ++ idx); + write_32_relocated (ptr, new_idx); + } +- break; +- case DW_MACRO_GNU_transparent_include: +- ptr += offset_len; +- break; +- default: +- error (1, 0, "Unhandled DW_MACRO op 0x%x", op); +- break; + } + } + +- if (rel_updated) +- macro_rel_updated = true; +- macro_sec = macro_sec->next; ++ op = read_8 (ptr); ++ if (!op) ++ continue; ++ switch(op) ++ { ++ case DW_MACRO_GNU_define: ++ case DW_MACRO_GNU_undef: ++ read_uleb128 (ptr); ++ ptr = ((unsigned char *) strchr ((char *) ptr, '\0') ++ + 1); ++ break; ++ case DW_MACRO_GNU_start_file: ++ read_uleb128 (ptr); ++ read_uleb128 (ptr); ++ break; ++ case DW_MACRO_GNU_end_file: ++ break; ++ case DW_MACRO_GNU_define_indirect: ++ case DW_MACRO_GNU_undef_indirect: ++ read_uleb128 (ptr); ++ if (phase == 0) ++ { ++ size_t idx = read_32_relocated (ptr); ++ record_existing_string_entry_idx (&dso->strings, ++ idx); ++ } ++ else ++ { ++ struct stridxentry *entry; ++ size_t idx, new_idx; ++ idx = do_read_32_relocated (ptr); ++ entry = string_find_entry (&dso->strings, idx); ++ new_idx = strent_offset (entry->entry); ++ write_32_relocated (ptr, new_idx); ++ } ++ break; ++ case DW_MACRO_GNU_transparent_include: ++ ptr += offset_len; ++ break; ++ default: ++ error (1, 0, "Unhandled DW_MACRO op 0x%x", op); ++ break; ++ } + } +- } + +- /* Same for the debug_str section. Make sure everything is +- in place for phase 1 updating of debug_info +- references. */ +- if (phase == 0 && need_strp_update) +- { +- Strtab *strtab = dso->strings.str_tab; +- Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data; +- int strndx = debug_sections[DEBUG_STR].sec; +- Elf_Scn *strscn = dso->scn[strndx]; +- +- /* Out with the old. */ +- strdata->d_size = 0; +- /* In with the new. */ +- strdata = elf_newdata (strscn); +- +- /* We really should check whether we had enough memory, +- but the old ebl version will just abort on out of +- memory... */ +- strtab_finalize (strtab, strdata); +- debug_sections[DEBUG_STR].size = strdata->d_size; +- dso->strings.str_buf = strdata->d_buf; ++ if (rel_updated) ++ macro_rel_updated = true; ++ macro_sec = macro_sec->next; + } ++ } + ++ /* Same for the debug_str section. Make sure everything is ++ in place for phase 1 updating of debug_info ++ references. */ ++ if (phase == 0 && need_strp_update) ++ { ++ Strtab *strtab = dso->strings.str_tab; ++ Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data; ++ int strndx = debug_sections[DEBUG_STR].sec; ++ Elf_Scn *strscn = dso->scn[strndx]; ++ ++ /* Out with the old. */ ++ strdata->d_size = 0; ++ /* In with the new. */ ++ strdata = elf_newdata (strscn); ++ ++ /* We really should check whether we had enough memory, ++ but the old ebl version will just abort on out of ++ memory... */ ++ strtab_finalize (strtab, strdata); ++ debug_sections[DEBUG_STR].size = strdata->d_size; ++ dso->strings.str_buf = strdata->d_buf; + } + +- /* After phase 1 we might have rewritten the debug_info with +- new strp, strings and/or linep offsets. */ +- if (need_strp_update || need_string_replacement || need_stmt_update) +- dirty_section (DEBUG_INFO); +- if (need_strp_update || need_stmt_update) +- dirty_section (DEBUG_MACRO); +- if (need_stmt_update) +- dirty_section (DEBUG_LINE); ++ } ++ ++ /* After phase 1 we might have rewritten the debug_info with ++ new strp, strings and/or linep offsets. */ ++ if (need_strp_update || need_string_replacement || need_stmt_update) ++ dirty_section (DEBUG_INFO); ++ if (need_strp_update || need_stmt_update) ++ dirty_section (DEBUG_MACRO); ++ if (need_stmt_update) ++ dirty_section (DEBUG_LINE); + +- /* Update any relocations addends we might have touched. */ +- if (info_rel_updated) +- update_rela_data (dso, &debug_sections[DEBUG_INFO]); ++ /* Update any relocations addends we might have touched. */ ++ if (info_rel_updated) ++ update_rela_data (dso, &debug_sections[DEBUG_INFO]); + +- if (macro_rel_updated) ++ if (macro_rel_updated) ++ { ++ struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO]; ++ while (macro_sec != NULL) + { +- struct debug_section *macro_sec = &debug_sections[DEBUG_MACRO]; +- while (macro_sec != NULL) +- { +- update_rela_data (dso, macro_sec); +- macro_sec = macro_sec->next; +- } ++ update_rela_data (dso, macro_sec); ++ macro_sec = macro_sec->next; + } + } + +-- +2.18.4 + diff --git a/SOURCES/0003-debugedit-Fix-missing-relocation-of-.debug_types-sec.patch b/SOURCES/0003-debugedit-Fix-missing-relocation-of-.debug_types-sec.patch new file mode 100644 index 0000000..dd4abb1 --- /dev/null +++ b/SOURCES/0003-debugedit-Fix-missing-relocation-of-.debug_types-sec.patch @@ -0,0 +1,269 @@ +From 8cd4d5046d7cb1bc16f01e77a5ff50eca8d9da3d Mon Sep 17 00:00:00 2001 +From: Jan Kratochvil +Date: Sat, 1 Aug 2020 10:45:47 +0200 +Subject: [PATCH 3/6] debugedit: Fix missing relocation of .debug_types + section. + +--- + tools/debugedit.c | 123 ++++++++++++++++++++++++++++++---------------- + 1 file changed, 80 insertions(+), 43 deletions(-) + +diff --git a/tools/debugedit.c b/tools/debugedit.c +index cad0cc349..87c1cd622 100644 +--- a/tools/debugedit.c ++++ b/tools/debugedit.c +@@ -433,7 +433,8 @@ typedef struct debug_section + int sec, relsec; + REL *relbuf; + REL *relend; +- struct debug_section *next; /* Only happens for COMDAT .debug_macro. */ ++ /* Only happens for COMDAT .debug_macro and .debug_types. */ ++ struct debug_section *next; + } debug_section; + + static debug_section debug_sections[] = +@@ -1269,7 +1270,9 @@ static int dirty_elf; + static void + dirty_section (unsigned int sec) + { +- elf_flagdata (debug_sections[sec].elf_data, ELF_C_SET, ELF_F_DIRTY); ++ for (struct debug_section *secp = &debug_sections[sec]; secp != NULL; ++ secp = secp->next) ++ elf_flagdata (secp->elf_data, ELF_C_SET, ELF_F_DIRTY); + dirty_elf = 1; + } + +@@ -1469,12 +1472,7 @@ read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir) + + if (get_line_table (dso, off, &table) == false + || table == NULL) +- { +- if (table != NULL) +- error (0, 0, ".debug_line offset 0x%x referenced multiple times", +- off); +- return false; +- } ++ return false; + + /* Skip to the directory table. The rest of the header has already + been read and checked by get_line_table. */ +@@ -1965,22 +1963,25 @@ line_rel_cmp (const void *a, const void *b) + } + + static int +-edit_info (DSO *dso, int phase) ++edit_info (DSO *dso, int phase, struct debug_section *sec) + { + unsigned char *ptr, *endcu, *endsec; + uint32_t value; + htab_t abbrev; + struct abbrev_tag tag, *t; + +- ptr = debug_sections[DEBUG_INFO].data; +- setup_relbuf(dso, &debug_sections[DEBUG_INFO], &reltype); +- endsec = ptr + debug_sections[DEBUG_INFO].size; ++ ptr = sec->data; ++ if (ptr == NULL) ++ return 0; ++ ++ setup_relbuf(dso, sec, &reltype); ++ endsec = ptr + sec->size; + while (ptr < endsec) + { +- if (ptr + 11 > endsec) ++ if (ptr + (sec == &debug_sections[DEBUG_INFO] ? 11 : 23) > endsec) + { +- error (0, 0, "%s: .debug_info CU header too small", +- dso->filename); ++ error (0, 0, "%s: %s CU header too small", ++ dso->filename, sec->name); + return 1; + } + +@@ -1994,7 +1995,7 @@ edit_info (DSO *dso, int phase) + + if (endcu > endsec) + { +- error (0, 0, "%s: .debug_info too small", dso->filename); ++ error (0, 0, "%s: %s too small", dso->filename, sec->name); + return 1; + } + +@@ -2034,6 +2035,9 @@ edit_info (DSO *dso, int phase) + return 1; + } + ++ if (sec != &debug_sections[DEBUG_INFO]) ++ ptr += 12; /* Skip type_signature and type_offset. */ ++ + abbrev = read_abbrev (dso, + debug_sections[DEBUG_ABBREV].data + value); + if (abbrev == NULL) +@@ -2095,7 +2099,7 @@ edit_dwarf2 (DSO *dso) + struct debug_section *debug_sec = &debug_sections[j]; + if (debug_sections[j].data) + { +- if (j != DEBUG_MACRO) ++ if (j != DEBUG_MACRO && j != DEBUG_TYPES) + { + error (0, 0, "%s: Found two copies of %s section", + dso->filename, name); +@@ -2103,22 +2107,21 @@ edit_dwarf2 (DSO *dso) + } + else + { +- /* In relocatable files .debug_macro might +- appear multiple times as COMDAT +- section. */ ++ /* In relocatable files .debug_macro and .debug_types ++ might appear multiple times as COMDAT section. */ + struct debug_section *sec; + sec = calloc (sizeof (struct debug_section), 1); + if (sec == NULL) + error (1, errno, +- "%s: Could not allocate more macro sections", +- dso->filename); +- sec->name = ".debug_macro"; ++ "%s: Could not allocate more %s sections", ++ dso->filename, name); ++ sec->name = name; + +- struct debug_section *macro_sec = debug_sec; +- while (macro_sec->next != NULL) +- macro_sec = macro_sec->next; ++ struct debug_section *multi_sec = debug_sec; ++ while (multi_sec->next != NULL) ++ multi_sec = multi_sec->next; + +- macro_sec->next = sec; ++ multi_sec->next = sec; + debug_sec = sec; + } + } +@@ -2155,23 +2158,23 @@ edit_dwarf2 (DSO *dso) + + (dso->shdr[i].sh_type == SHT_RELA), + debug_sections[j].name) == 0) + { +- if (j == DEBUG_MACRO) ++ if (j == DEBUG_MACRO || j == DEBUG_TYPES) + { + /* Pick the correct one. */ + int rel_target = dso->shdr[i].sh_info; +- struct debug_section *macro_sec = &debug_sections[j]; +- while (macro_sec != NULL) ++ struct debug_section *multi_sec = &debug_sections[j]; ++ while (multi_sec != NULL) + { +- if (macro_sec->sec == rel_target) ++ if (multi_sec->sec == rel_target) + { +- macro_sec->relsec = i; ++ multi_sec->relsec = i; + break; + } +- macro_sec = macro_sec->next; ++ multi_sec = multi_sec->next; + } +- if (macro_sec == NULL) +- error (0, 1, "No .debug_macro reloc section: %s", +- dso->filename); ++ if (multi_sec == NULL) ++ error (0, 1, "No %s reloc section: %s", ++ debug_sections[j].name, dso->filename); + } + else + debug_sections[j].relsec = i; +@@ -2203,12 +2206,10 @@ edit_dwarf2 (DSO *dso) + if (debug_sections[DEBUG_INFO].data == NULL) + return 0; + +- unsigned char *ptr, *endcu, *endsec; +- uint32_t value; +- htab_t abbrev; +- struct abbrev_tag tag, *t; ++ unsigned char *ptr, *endsec; + int phase; + bool info_rel_updated = false; ++ bool types_rel_updated = false; + bool macro_rel_updated = false; + + for (phase = 0; phase < 2; phase++) +@@ -2221,13 +2222,26 @@ edit_dwarf2 (DSO *dso) + break; + + rel_updated = false; +- if (edit_info (dso, phase)) +- return 1; ++ if (edit_info (dso, phase, &debug_sections[DEBUG_INFO])) ++ return 1; + + /* Remember whether any .debug_info relocations might need + to be updated. */ + info_rel_updated = rel_updated; + ++ rel_updated = false; ++ struct debug_section *types_sec = &debug_sections[DEBUG_TYPES]; ++ while (types_sec != NULL) ++ { ++ if (edit_info (dso, phase, types_sec)) ++ return 1; ++ types_sec = types_sec->next; ++ } ++ ++ /* Remember whether any .debug_types relocations might need ++ to be updated. */ ++ types_rel_updated = rel_updated; ++ + /* We might have to recalculate/rewrite the debug_line + section. We need to do that before going into phase one + so we have all new offsets. We do this separately from +@@ -2475,8 +2489,11 @@ edit_dwarf2 (DSO *dso) + + /* After phase 1 we might have rewritten the debug_info with + new strp, strings and/or linep offsets. */ +- if (need_strp_update || need_string_replacement || need_stmt_update) ++ if (need_strp_update || need_string_replacement || need_stmt_update) { + dirty_section (DEBUG_INFO); ++ if (debug_sections[DEBUG_TYPES].data != NULL) ++ dirty_section (DEBUG_TYPES); ++ } + if (need_strp_update || need_stmt_update) + dirty_section (DEBUG_MACRO); + if (need_stmt_update) +@@ -2485,6 +2502,15 @@ edit_dwarf2 (DSO *dso) + /* Update any relocations addends we might have touched. */ + if (info_rel_updated) + update_rela_data (dso, &debug_sections[DEBUG_INFO]); ++ if (types_rel_updated) ++ { ++ struct debug_section *types_sec = &debug_sections[DEBUG_TYPES]; ++ while (types_sec != NULL) ++ { ++ update_rela_data (dso, types_sec); ++ types_sec = types_sec->next; ++ } ++ } + + if (macro_rel_updated) + { +@@ -3037,6 +3063,17 @@ main (int argc, char *argv[]) + macro_sec = next; + } + ++ /* In case there were multiple (COMDAT) .debug_types sections, ++ free them. */ ++ struct debug_section *types_sec = &debug_sections[DEBUG_TYPES]; ++ types_sec = types_sec->next; ++ while (types_sec != NULL) ++ { ++ struct debug_section *next = types_sec->next; ++ free (types_sec); ++ types_sec = next; ++ } ++ + poptFreeContext (optCon); + + return 0; +-- +2.18.4 + diff --git a/SOURCES/0004-NFC-debugedit-Move-code-to-separate-functions.patch b/SOURCES/0004-NFC-debugedit-Move-code-to-separate-functions.patch new file mode 100644 index 0000000..5f13953 --- /dev/null +++ b/SOURCES/0004-NFC-debugedit-Move-code-to-separate-functions.patch @@ -0,0 +1,455 @@ +From bab443ab4f756ef80f814af0353143f41e90e6a6 Mon Sep 17 00:00:00 2001 +From: Jan Kratochvil +Date: Mon, 17 Aug 2020 21:58:19 +0200 +Subject: [PATCH 4/6] [NFC] debugedit: Move code to separate functions. + +New functions edit_strp, skip_form and edit_attributes_str_comp_dir +called by edit_attributes. +Split part of read_dwarf2_line into a read_dwarf4_line function. +New function edit_dwarf2_any_str called by edit_dwarf2 at the end of +phase 0 to rebuild .debug_str. +--- + tools/debugedit.c | 367 ++++++++++++++++++++++++++-------------------- + 1 file changed, 212 insertions(+), 155 deletions(-) + +diff --git a/tools/debugedit.c b/tools/debugedit.c +index 87c1cd622..7464883c5 100644 +--- a/tools/debugedit.c ++++ b/tools/debugedit.c +@@ -1457,37 +1457,128 @@ edit_dwarf2_line (DSO *dso) + } + } + +-/* Called during phase zero for each debug_line table referenced from +- .debug_info. Outputs all source files seen and records any +- adjustments needed in the debug_list data structures. Returns true +- if line_table needs to be rewrite either the dir or file paths. */ ++/* Record or adjust (according to phase) DW_FORM_strp. */ ++static void ++edit_strp (DSO *dso, unsigned char *ptr, int phase, bool handled_strp) ++{ ++ unsigned char *ptr_orig = ptr; ++ ++ /* In the first pass we collect all strings, in the ++ second we put the new references back (if there are ++ any changes). */ ++ if (phase == 0) ++ { ++ /* handled_strp is set for attributes referring to ++ files. If it is set the string is already ++ recorded. */ ++ if (! handled_strp) ++ { ++ size_t idx = do_read_32_relocated (ptr); ++ record_existing_string_entry_idx (&dso->strings, idx); ++ } ++ } ++ else if (need_strp_update) /* && phase == 1 */ ++ { ++ struct stridxentry *entry; ++ size_t idx, new_idx; ++ idx = do_read_32_relocated (ptr); ++ entry = string_find_entry (&dso->strings, idx); ++ new_idx = strent_offset (entry->entry); ++ do_write_32_relocated (ptr, new_idx); ++ } ++ ++ assert (ptr == ptr_orig); ++} ++ ++/* Adjust *PTRP after the current *FORMP, update *FORMP for FORM_INDIRECT. */ ++static enum { FORM_OK, FORM_ERROR, FORM_INDIRECT } ++skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp) ++{ ++ size_t len = 0; ++ ++ switch (*formp) ++ { ++ case DW_FORM_ref_addr: ++ if (cu_version == 2) ++ *ptrp += ptr_size; ++ else ++ *ptrp += 4; ++ break; ++ case DW_FORM_flag_present: ++ break; ++ case DW_FORM_addr: ++ *ptrp += ptr_size; ++ break; ++ case DW_FORM_ref1: ++ case DW_FORM_flag: ++ case DW_FORM_data1: ++ ++*ptrp; ++ break; ++ case DW_FORM_ref2: ++ case DW_FORM_data2: ++ *ptrp += 2; ++ break; ++ case DW_FORM_ref4: ++ case DW_FORM_data4: ++ case DW_FORM_sec_offset: ++ *ptrp += 4; ++ break; ++ case DW_FORM_ref8: ++ case DW_FORM_data8: ++ case DW_FORM_ref_sig8: ++ *ptrp += 8; ++ break; ++ case DW_FORM_sdata: ++ case DW_FORM_ref_udata: ++ case DW_FORM_udata: ++ read_uleb128 (*ptrp); ++ break; ++ case DW_FORM_strp: ++ *ptrp += 4; ++ break; ++ case DW_FORM_string: ++ *ptrp = (unsigned char *) strchr ((char *)*ptrp, '\0') + 1; ++ break; ++ case DW_FORM_indirect: ++ *formp = read_uleb128 (*ptrp); ++ return FORM_INDIRECT; ++ case DW_FORM_block1: ++ len = *(*ptrp)++; ++ break; ++ case DW_FORM_block2: ++ len = read_16 (*ptrp); ++ *formp = DW_FORM_block1; ++ break; ++ case DW_FORM_block4: ++ len = read_32 (*ptrp); ++ *formp = DW_FORM_block1; ++ break; ++ case DW_FORM_block: ++ case DW_FORM_exprloc: ++ len = read_uleb128 (*ptrp); ++ *formp = DW_FORM_block1; ++ assert (len < UINT_MAX); ++ break; ++ default: ++ error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, *formp); ++ return FORM_ERROR; ++ } ++ ++ if (*formp == DW_FORM_block1) ++ *ptrp += len; ++ ++ return FORM_OK; ++} ++ ++/* Part of read_dwarf2_line processing DWARF-4. */ + static bool +-read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir) ++read_dwarf4_line (DSO *dso, unsigned char *ptr, char *comp_dir, ++ struct line_table *table) + { +- unsigned char *ptr, *dir; + unsigned char **dirt; + uint32_t value, dirt_cnt; + size_t comp_dir_len = !comp_dir ? 0 : strlen (comp_dir); +- struct line_table *table; +- +- if (get_line_table (dso, off, &table) == false +- || table == NULL) +- return false; +- +- /* Skip to the directory table. The rest of the header has already +- been read and checked by get_line_table. */ +- ptr = debug_sections[DEBUG_LINE].data + off; +- ptr += (4 /* unit len */ +- + 2 /* version */ +- + 4 /* header len */ +- + 1 /* min instr len */ +- + (table->version >= 4) /* max op per instr, if version >= 4 */ +- + 1 /* default is stmt */ +- + 1 /* line base */ +- + 1 /* line range */ +- + 1 /* opcode base */ +- + table->opcode_base - 1); /* opcode len table */ +- dir = ptr; ++ unsigned char *dir = ptr; + + /* dir table: */ + value = 1; +@@ -1620,6 +1711,40 @@ read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir) + read_uleb128 (ptr); + } + ++ return true; ++} ++ ++/* Called during phase zero for each debug_line table referenced from ++ .debug_info. Outputs all source files seen and records any ++ adjustments needed in the debug_list data structures. Returns true ++ if line_table needs to be rewrite either the dir or file paths. */ ++static bool ++read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir) ++{ ++ unsigned char *ptr; ++ struct line_table *table; ++ ++ if (get_line_table (dso, off, &table) == false ++ || table == NULL) ++ return false; ++ ++ /* Skip to the directory table. The rest of the header has already ++ been read and checked by get_line_table. */ ++ ptr = debug_sections[DEBUG_LINE].data + off; ++ ptr += (4 /* unit len */ ++ + 2 /* version */ ++ + 4 /* header len */ ++ + 1 /* min instr len */ ++ + (table->version >= 4) /* max op per instr, if version >= 4 */ ++ + 1 /* default is stmt */ ++ + 1 /* line base */ ++ + 1 /* line range */ ++ + 1 /* opcode base */ ++ + table->opcode_base - 1); /* opcode len table */ ++ ++ if (! read_dwarf4_line (dso, ptr, comp_dir, table)) ++ return false; ++ + dso->lines.debug_lines_len += 4 + table->unit_length + table->size_diff; + return table->replace_dirs || table->replace_files; + } +@@ -1637,6 +1762,33 @@ find_new_list_offs (struct debug_lines *lines, size_t idx) + return table->new_idx; + } + ++/* Read DW_FORM_strp collecting compilation directory. */ ++static void ++edit_attributes_str_comp_dir (DSO *dso, unsigned char **ptrp, int phase, ++ char **comp_dirp, bool *handled_strpp) ++{ ++ const char *dir; ++ size_t idx = do_read_32_relocated (*ptrp); ++ /* In phase zero we collect the comp_dir. */ ++ if (phase == 0) ++ { ++ if (idx >= debug_sections[DEBUG_STR].size) ++ error (1, 0, "%s: Bad string pointer index %zd for comp_dir", ++ dso->filename, idx); ++ dir = (char *) debug_sections[DEBUG_STR].data + idx; ++ ++ free (*comp_dirp); ++ *comp_dirp = strdup (dir); ++ } ++ ++ if (dest_dir != NULL && phase == 0) ++ { ++ if (record_file_string_entry_idx (&dso->strings, idx)) ++ need_strp_update = true; ++ *handled_strpp = true; ++ } ++} ++ + /* This scans the attributes of one DIE described by the given abbrev_tag. + PTR points to the data in the debug_info. It will be advanced till all + abbrev data is consumed. In phase zero data is collected, in phase one +@@ -1655,7 +1807,6 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) + for (i = 0; i < t->nattr; ++i) + { + uint32_t form = t->attr[i].form; +- size_t len = 0; + while (1) + { + /* Whether we already handled a string as file for this +@@ -1743,29 +1894,8 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) + } + else if (form == DW_FORM_strp && + debug_sections[DEBUG_STR].data) +- { +- const char *dir; +- size_t idx = do_read_32_relocated (ptr); +- /* In phase zero we collect the comp_dir. */ +- if (phase == 0) +- { +- if (idx >= debug_sections[DEBUG_STR].size) +- error (1, 0, +- "%s: Bad string pointer index %zd for comp_dir", +- dso->filename, idx); +- dir = (char *) debug_sections[DEBUG_STR].data + idx; +- +- free (comp_dir); +- comp_dir = strdup (dir); +- } +- +- if (dest_dir != NULL && phase == 0) +- { +- if (record_file_string_entry_idx (&dso->strings, idx)) +- need_strp_update = true; +- handled_strp = true; +- } +- } ++ edit_attributes_str_comp_dir (dso, &ptr, phase, &comp_dir, ++ &handled_strp); + } + else if ((t->tag == DW_TAG_compile_unit + || t->tag == DW_TAG_partial_unit) +@@ -1815,99 +1945,21 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) + + switch (form) + { +- case DW_FORM_ref_addr: +- if (cu_version == 2) +- ptr += ptr_size; +- else +- ptr += 4; +- break; +- case DW_FORM_flag_present: +- break; +- case DW_FORM_addr: +- ptr += ptr_size; +- break; +- case DW_FORM_ref1: +- case DW_FORM_flag: +- case DW_FORM_data1: +- ++ptr; +- break; +- case DW_FORM_ref2: +- case DW_FORM_data2: +- ptr += 2; +- break; +- case DW_FORM_ref4: +- case DW_FORM_data4: +- case DW_FORM_sec_offset: +- ptr += 4; +- break; +- case DW_FORM_ref8: +- case DW_FORM_data8: +- case DW_FORM_ref_sig8: +- ptr += 8; +- break; +- case DW_FORM_sdata: +- case DW_FORM_ref_udata: +- case DW_FORM_udata: +- read_uleb128 (ptr); +- break; + case DW_FORM_strp: +- /* In the first pass we collect all strings, in the +- second we put the new references back (if there are +- any changes). */ +- if (phase == 0) +- { +- /* handled_strp is set for attributes referring to +- files. If it is set the string is already +- recorded. */ +- if (! handled_strp) +- { +- size_t idx = do_read_32_relocated (ptr); +- record_existing_string_entry_idx (&dso->strings, idx); +- } +- } +- else if (need_strp_update) /* && phase == 1 */ +- { +- struct stridxentry *entry; +- size_t idx, new_idx; +- idx = do_read_32_relocated (ptr); +- entry = string_find_entry (&dso->strings, idx); +- new_idx = strent_offset (entry->entry); +- do_write_32_relocated (ptr, new_idx); +- } +- ptr += 4; +- break; +- case DW_FORM_string: +- ptr = (unsigned char *) strchr ((char *)ptr, '\0') + 1; +- break; +- case DW_FORM_indirect: +- form = read_uleb128 (ptr); +- continue; +- case DW_FORM_block1: +- len = *ptr++; +- break; +- case DW_FORM_block2: +- len = read_16 (ptr); +- form = DW_FORM_block1; ++ edit_strp (dso, ptr, phase, handled_strp); + break; +- case DW_FORM_block4: +- len = read_32 (ptr); +- form = DW_FORM_block1; +- break; +- case DW_FORM_block: +- case DW_FORM_exprloc: +- len = read_uleb128 (ptr); +- form = DW_FORM_block1; +- assert (len < UINT_MAX); ++ } ++ ++ switch (skip_form (dso, &form, &ptr)) ++ { ++ case FORM_OK: + break; +- default: +- error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, +- form); ++ case FORM_ERROR: + return NULL; ++ case FORM_INDIRECT: ++ continue; + } + +- if (form == DW_FORM_block1) +- ptr += len; +- + break; + } + } +@@ -2068,6 +2120,28 @@ edit_info (DSO *dso, int phase, struct debug_section *sec) + return 0; + } + ++/* Rebuild .debug_str. */ ++static void ++edit_dwarf2_any_str (DSO *dso) ++{ ++ Strtab *strtab = dso->strings.str_tab; ++ Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data; ++ int strndx = debug_sections[DEBUG_STR].sec; ++ Elf_Scn *strscn = dso->scn[strndx]; ++ ++ /* Out with the old. */ ++ strdata->d_size = 0; ++ /* In with the new. */ ++ strdata = elf_newdata (strscn); ++ ++ /* We really should check whether we had enough memory, ++ but the old ebl version will just abort on out of ++ memory... */ ++ strtab_finalize (strtab, strdata); ++ debug_sections[DEBUG_STR].size = strdata->d_size; ++ dso->strings.str_buf = strdata->d_buf; ++} ++ + static int + edit_dwarf2 (DSO *dso) + { +@@ -2466,24 +2540,7 @@ edit_dwarf2 (DSO *dso) + in place for phase 1 updating of debug_info + references. */ + if (phase == 0 && need_strp_update) +- { +- Strtab *strtab = dso->strings.str_tab; +- Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data; +- int strndx = debug_sections[DEBUG_STR].sec; +- Elf_Scn *strscn = dso->scn[strndx]; +- +- /* Out with the old. */ +- strdata->d_size = 0; +- /* In with the new. */ +- strdata = elf_newdata (strscn); +- +- /* We really should check whether we had enough memory, +- but the old ebl version will just abort on out of +- memory... */ +- strtab_finalize (strtab, strdata); +- debug_sections[DEBUG_STR].size = strdata->d_size; +- dso->strings.str_buf = strdata->d_buf; +- } ++ edit_dwarf2_any_str (dso); + + } + +-- +2.18.4 + diff --git a/SOURCES/0005-debugedit-Implement-DWARF-5-unit-header-and-new-form.patch b/SOURCES/0005-debugedit-Implement-DWARF-5-unit-header-and-new-form.patch new file mode 100644 index 0000000..4bef1ef --- /dev/null +++ b/SOURCES/0005-debugedit-Implement-DWARF-5-unit-header-and-new-form.patch @@ -0,0 +1,217 @@ +From 8b5dcb4c2175ac706a4e1c34ce83301213800689 Mon Sep 17 00:00:00 2001 +From: Jan Kratochvil +Date: Mon, 18 Jan 2021 22:56:53 +0100 +Subject: [PATCH 5/6] debugedit: Implement DWARF-5 unit header and new forms + parsing. + +Recognize the various new DWARF5 .debug sections. +Parse and skip new DWARF5 forms in read_abbrev and skip_form. +Read DWARF5 unit headers for compile and partial units in edit_info. + +This is enough to be able to process gcc -gdwarf-5 produced binaries +without the new DWARF5 .debug_line format (which isn't produced with +binutils < 2.36). + +Patches slightly edited/merged by Mark Wielaard +--- + tools/debugedit.c | 88 +++++++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 81 insertions(+), 7 deletions(-) + +diff --git a/tools/debugedit.c b/tools/debugedit.c +index 7464883c5..be5fee85b 100644 +--- a/tools/debugedit.c ++++ b/tools/debugedit.c +@@ -453,6 +453,11 @@ static debug_section debug_sections[] = + #define DEBUG_TYPES 11 + #define DEBUG_MACRO 12 + #define DEBUG_GDB_SCRIPT 13 ++#define DEBUG_RNGLISTS 14 ++#define DEBUG_LINE_STR 15 ++#define DEBUG_ADDR 16 ++#define DEBUG_STR_OFFSETS 17 ++#define DEBUG_LOCLISTS 18 + { ".debug_info", NULL, NULL, 0, 0, 0 }, + { ".debug_abbrev", NULL, NULL, 0, 0, 0 }, + { ".debug_line", NULL, NULL, 0, 0, 0 }, +@@ -467,6 +472,11 @@ static debug_section debug_sections[] = + { ".debug_types", NULL, NULL, 0, 0, 0 }, + { ".debug_macro", NULL, NULL, 0, 0, 0 }, + { ".debug_gdb_scripts", NULL, NULL, 0, 0, 0 }, ++ { ".debug_rnglists", NULL, NULL, 0, 0, 0 }, ++ { ".debug_line_str", NULL, NULL, 0, 0, 0 }, ++ { ".debug_addr", NULL, NULL, 0, 0, 0 }, ++ { ".debug_str_offsets", NULL, NULL, 0, 0, 0 }, ++ { ".debug_loclists", NULL, NULL, 0, 0, 0 }, + { NULL, NULL, NULL, 0, 0, 0 } + }; + +@@ -755,12 +765,28 @@ no_memory: + } + form = read_uleb128 (ptr); + if (form == 2 +- || (form > DW_FORM_flag_present && form != DW_FORM_ref_sig8)) ++ || (form > DW_FORM_flag_present ++ && !(form == DW_FORM_ref_sig8 ++ || form == DW_FORM_data16 ++ || form == DW_FORM_implicit_const ++ || form == DW_FORM_addrx ++ || form == DW_FORM_loclistx ++ || form == DW_FORM_rnglistx ++ || form == DW_FORM_addrx1 ++ || form == DW_FORM_addrx2 ++ || form == DW_FORM_addrx3 ++ || form == DW_FORM_addrx4))) + { +- error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, form); ++ error (0, 0, "%s: Unknown DWARF DW_FORM_0x%x", dso->filename, ++ form); + htab_delete (h); + return NULL; + } ++ if (form == DW_FORM_implicit_const) ++ { ++ /* It is SLEB128 but the value is dropped anyway. */ ++ read_uleb128 (ptr); ++ } + + t->attr[t->nattr].attr = attr; + t->attr[t->nattr++].form = form; +@@ -1505,6 +1531,7 @@ skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp) + *ptrp += 4; + break; + case DW_FORM_flag_present: ++ case DW_FORM_implicit_const: + break; + case DW_FORM_addr: + *ptrp += ptr_size; +@@ -1512,14 +1539,24 @@ skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp) + case DW_FORM_ref1: + case DW_FORM_flag: + case DW_FORM_data1: ++ case DW_FORM_strx1: ++ case DW_FORM_addrx1: + ++*ptrp; + break; + case DW_FORM_ref2: + case DW_FORM_data2: ++ case DW_FORM_strx2: ++ case DW_FORM_addrx2: + *ptrp += 2; + break; ++ case DW_FORM_strx3: ++ case DW_FORM_addrx3: ++ *ptrp += 3; ++ break; + case DW_FORM_ref4: + case DW_FORM_data4: ++ case DW_FORM_strx4: ++ case DW_FORM_addrx4: + case DW_FORM_sec_offset: + *ptrp += 4; + break; +@@ -1528,12 +1565,20 @@ skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp) + case DW_FORM_ref_sig8: + *ptrp += 8; + break; ++ case DW_FORM_data16: ++ *ptrp += 16; ++ break; + case DW_FORM_sdata: + case DW_FORM_ref_udata: + case DW_FORM_udata: ++ case DW_FORM_strx: ++ case DW_FORM_loclistx: ++ case DW_FORM_rnglistx: ++ case DW_FORM_addrx: + read_uleb128 (*ptrp); + break; + case DW_FORM_strp: ++ case DW_FORM_line_strp: + *ptrp += 4; + break; + case DW_FORM_string: +@@ -1560,7 +1605,7 @@ skip_form (DSO *dso, uint32_t *formp, unsigned char **ptrp) + assert (len < UINT_MAX); + break; + default: +- error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, *formp); ++ error (0, 0, "%s: Unknown DWARF DW_FORM_0x%x", dso->filename, *formp); + return FORM_ERROR; + } + +@@ -2030,7 +2075,10 @@ edit_info (DSO *dso, int phase, struct debug_section *sec) + endsec = ptr + sec->size; + while (ptr < endsec) + { +- if (ptr + (sec == &debug_sections[DEBUG_INFO] ? 11 : 23) > endsec) ++ unsigned char *cu_start = ptr; ++ ++ /* header size, version, unit_type, ptr_size. */ ++ if (ptr + 4 + 2 + 1 + 1 > endsec) + { + error (0, 0, "%s: %s CU header too small", + dso->filename, sec->name); +@@ -2052,13 +2100,36 @@ edit_info (DSO *dso, int phase, struct debug_section *sec) + } + + cu_version = read_16 (ptr); +- if (cu_version != 2 && cu_version != 3 && cu_version != 4) ++ if (cu_version != 2 && cu_version != 3 && cu_version != 4 ++ && cu_version != 5) + { + error (0, 0, "%s: DWARF version %d unhandled", dso->filename, + cu_version); + return 1; + } + ++ int cu_ptr_size = 0; ++ ++ if (cu_version >= 5) ++ { ++ uint8_t unit_type = read_8 (ptr); ++ if (unit_type != DW_UT_compile && unit_type != DW_UT_partial) ++ { ++ error (0, 0, "%s: Unit type %u unhandled", dso->filename, ++ unit_type); ++ return 1; ++ } ++ ++ cu_ptr_size = read_8 (ptr); ++ } ++ ++ unsigned char *header_end = (cu_start + 23 + (cu_version < 5 ? 0 : 1)); ++ if (header_end > endsec) ++ { ++ error (0, 0, "%s: %s CU header too small", dso->filename, sec->name); ++ return 1; ++ } ++ + value = read_32_relocated (ptr); + if (value >= debug_sections[DEBUG_ABBREV].size) + { +@@ -2070,9 +2141,12 @@ edit_info (DSO *dso, int phase, struct debug_section *sec) + return 1; + } + ++ if (cu_version < 5) ++ cu_ptr_size = read_8 (ptr); ++ + if (ptr_size == 0) + { +- ptr_size = read_8 (ptr); ++ ptr_size = cu_ptr_size; + if (ptr_size != 4 && ptr_size != 8) + { + error (0, 0, "%s: Invalid DWARF pointer size %d", +@@ -2080,7 +2154,7 @@ edit_info (DSO *dso, int phase, struct debug_section *sec) + return 1; + } + } +- else if (read_8 (ptr) != ptr_size) ++ else if (cu_ptr_size != ptr_size) + { + error (0, 0, "%s: DWARF pointer size differs between CUs", + dso->filename); +-- +2.18.4 + diff --git a/SOURCES/0006-debugedit-Handle-DWARF-5-debug_line-and-debug_line_s.patch b/SOURCES/0006-debugedit-Handle-DWARF-5-debug_line-and-debug_line_s.patch new file mode 100644 index 0000000..1f1a966 --- /dev/null +++ b/SOURCES/0006-debugedit-Handle-DWARF-5-debug_line-and-debug_line_s.patch @@ -0,0 +1,772 @@ +From d9947f2dc0c2cd812f8e64380d5f6f53705a5280 Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Tue, 19 Jan 2021 04:12:33 +0100 +Subject: [PATCH 6/6] debugedit: Handle DWARF-5 debug_line and debug_line_str. + +Handle the new DWARF5 .debug_line tables and the new DW_FORM_line_strp. +DWARF5 tables are handled separately from the earlier tables. They +will never change size, but they do need updates to the .debug_str +or .debug_line_str references. + +Based on a patch from Jan Kratochvil +--- + tools/debugedit.c | 471 ++++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 410 insertions(+), 61 deletions(-) + +diff --git a/tools/debugedit.c b/tools/debugedit.c +index be5fee85b..d6a0058e9 100644 +--- a/tools/debugedit.c ++++ b/tools/debugedit.c +@@ -103,6 +103,8 @@ static bool need_string_replacement = false; + /* Whether we need to do any updates of the string indexes (DW_FORM_strp) + in debug_info for string indexes. */ + static bool need_strp_update = false; ++/* Likewise for DW_FORM_line_strp. */ ++static bool need_line_strp_update = false; + /* If the debug_line changes size we will need to update the + DW_AT_stmt_list attributes indexes in the debug_info. */ + static bool need_stmt_update = false; +@@ -192,7 +194,7 @@ typedef struct + const char *filename; + int lastscn; + size_t phnum; +- struct strings strings; ++ struct strings debug_str, debug_line_str; + struct debug_lines lines; + GElf_Shdr shdr[0]; + } DSO; +@@ -553,10 +555,11 @@ setup_relbuf (DSO *dso, debug_section *sec, int *reltype) + /* Relocations against section symbols are uninteresting in REL. */ + if (dso->shdr[i].sh_type == SHT_REL && sym.st_value == 0) + continue; +- /* Only consider relocations against .debug_str, .debug_line +- and .debug_abbrev. */ ++ /* Only consider relocations against .debug_str, .debug_line, ++ .debug_line_str, and .debug_abbrev. */ + if (sym.st_shndx != debug_sections[DEBUG_STR].sec + && sym.st_shndx != debug_sections[DEBUG_LINE].sec ++ && sym.st_shndx != debug_sections[DEBUG_LINE_STR].sec + && sym.st_shndx != debug_sections[DEBUG_ABBREV].sec) + continue; + rela.r_addend += sym.st_value; +@@ -768,6 +771,7 @@ no_memory: + || (form > DW_FORM_flag_present + && !(form == DW_FORM_ref_sig8 + || form == DW_FORM_data16 ++ || form == DW_FORM_line_strp + || form == DW_FORM_implicit_const + || form == DW_FORM_addrx + || form == DW_FORM_loclistx +@@ -1049,17 +1053,20 @@ string_find_entry (struct strings *strings, size_t old_idx) + a replacement file string has been recorded for it, otherwise + returns false. */ + static bool +-record_file_string_entry_idx (struct strings *strings, size_t old_idx) ++record_file_string_entry_idx (bool line_strp, DSO *dso, size_t old_idx) + { ++ struct strings *strings = line_strp ? &dso->debug_line_str : &dso->debug_str; + bool ret = false; + struct stridxentry *entry = string_find_new_entry (strings, old_idx); + if (entry != NULL) + { +- if (old_idx >= debug_sections[DEBUG_STR].size) +- error (1, 0, "Bad string pointer index %zd", old_idx); ++ debug_section *sec = &debug_sections[line_strp ++ ? DEBUG_LINE_STR : DEBUG_STR]; ++ if (old_idx >= sec->size) ++ error (1, 0, "Bad string pointer index %zd (%s)", old_idx, sec->name); + + Strent *strent; +- const char *old_str = (char *)debug_sections[DEBUG_STR].data + old_idx; ++ const char *old_str = (char *)sec->data + old_idx; + const char *file = skip_dir_prefix (old_str, base_dir); + if (file == NULL) + { +@@ -1103,15 +1110,18 @@ record_file_string_entry_idx (struct strings *strings, size_t old_idx) + base_dir with dest_dir, just records the existing string associated + with the index. */ + static void +-record_existing_string_entry_idx (struct strings *strings, size_t old_idx) ++record_existing_string_entry_idx (bool line_strp, DSO *dso, size_t old_idx) + { ++ struct strings *strings = line_strp ? &dso->debug_line_str : &dso->debug_str; + struct stridxentry *entry = string_find_new_entry (strings, old_idx); + if (entry != NULL) + { +- if (old_idx >= debug_sections[DEBUG_STR].size) +- error (1, 0, "Bad string pointer index %zd", old_idx); ++ debug_section *sec = &debug_sections[line_strp ++ ? DEBUG_LINE_STR : DEBUG_STR]; ++ if (old_idx >= sec->size) ++ error (1, 0, "Bad string pointer index %zd (%s)", old_idx, sec->name); + +- const char *str = (char *)debug_sections[DEBUG_STR].data + old_idx; ++ const char *str = (char *)sec->data + old_idx; + Strent *strent = strtab_add_len (strings->str_tab, + str, strlen (str) + 1); + if (strent == NULL) +@@ -1244,13 +1254,28 @@ get_line_table (DSO *dso, size_t off, struct line_table **table) + + /* version */ + t->version = read_16 (ptr); +- if (t->version != 2 && t->version != 3 && t->version != 4) ++ if (t->version != 2 && t->version != 3 && t->version != 4 && t->version != 5) + { + error (0, 0, "%s: DWARF version %d unhandled", dso->filename, + t->version); + return false; + } + ++ if (t->version >= 5) ++ { ++ /* address_size */ ++ assert (ptr_size != 0); ++ if (ptr_size != read_8 (ptr)) ++ { ++ error (0, 0, "%s: .debug_line address size differs from .debug_info", ++ dso->filename); ++ return false; ++ } ++ ++ /* segment_selector_size */ ++ (void) read_8 (ptr); ++ } ++ + /* header_length */ + unsigned char *endprol = ptr + 4; + t->header_length = read_32 (ptr); +@@ -1343,7 +1368,9 @@ edit_dwarf2_line (DSO *dso) + + linedata->d_size = dso->lines.debug_lines_len; + linedata->d_buf = dso->lines.line_buf; ++ debug_sections[DEBUG_LINE].data = linedata->d_buf; + debug_sections[DEBUG_LINE].size = linedata->d_size; ++ debug_sections[DEBUG_LINE].elf_data = linedata; + + /* Make sure the line tables are sorted on the old index. */ + qsort (dso->lines.table, dso->lines.used, sizeof (struct line_table), +@@ -1483,9 +1510,10 @@ edit_dwarf2_line (DSO *dso) + } + } + +-/* Record or adjust (according to phase) DW_FORM_strp. */ ++/* Record or adjust (according to phase) DW_FORM_strp or DW_FORM_line_strp. */ + static void +-edit_strp (DSO *dso, unsigned char *ptr, int phase, bool handled_strp) ++edit_strp (DSO *dso, bool line_strp, unsigned char *ptr, int phase, ++ bool handled_strp) + { + unsigned char *ptr_orig = ptr; + +@@ -1500,15 +1528,18 @@ edit_strp (DSO *dso, unsigned char *ptr, int phase, bool handled_strp) + if (! handled_strp) + { + size_t idx = do_read_32_relocated (ptr); +- record_existing_string_entry_idx (&dso->strings, idx); ++ record_existing_string_entry_idx (line_strp, dso, idx); + } + } +- else if (need_strp_update) /* && phase == 1 */ ++ else if (line_strp ++ ? need_line_strp_update : need_strp_update) /* && phase == 1 */ + { + struct stridxentry *entry; + size_t idx, new_idx; ++ struct strings *strings = (line_strp ++ ? &dso->debug_line_str : &dso->debug_str); + idx = do_read_32_relocated (ptr); +- entry = string_find_entry (&dso->strings, idx); ++ entry = string_find_entry (strings, idx); + new_idx = strent_offset (entry->entry); + do_write_32_relocated (ptr, new_idx); + } +@@ -1759,6 +1790,254 @@ read_dwarf4_line (DSO *dso, unsigned char *ptr, char *comp_dir, + return true; + } + ++/* Called by read_dwarf5_line first for directories and then file ++ names as they both have the same format. */ ++static bool ++read_dwarf5_line_entries (DSO *dso, unsigned char **ptrp, ++ struct line_table *table, int phase, ++ char ***dirs, int *ndir, ++ const char *entry_name) ++{ ++ /* directory_entry_format_count */ ++ /* file_name_entry_format_count */ ++ unsigned format_count = read_8 (*ptrp); ++ ++ unsigned char *formats = *ptrp; ++ ++ /* directory_entry_format */ ++ /* file_name_entry_format */ ++ for (unsigned formati = 0; formati < format_count; ++formati) ++ { ++ read_uleb128 (*ptrp); ++ read_uleb128 (*ptrp); ++ } ++ ++ /* directories_count */ ++ /* file_names_count */ ++ unsigned entry_count = read_uleb128 (*ptrp); ++ ++ bool collecting_dirs = dest_dir && phase == 0 && *dirs == NULL; ++ bool writing_files = dest_dir && phase == 0 && *dirs != NULL; ++ if (collecting_dirs) ++ { ++ *ndir = entry_count; ++ *dirs = malloc (entry_count * sizeof (char *)); ++ if (*dirs == NULL) ++ error (1, errno, "%s: Could not allocate debug_line dirs", ++ dso->filename); ++ } ++ ++ /* directories */ ++ /* file_names */ ++ for (unsigned entryi = 0; entryi < entry_count; ++entryi) ++ { ++ char *dir = NULL; ++ char *file = NULL;; ++ unsigned char *format_ptr = formats; ++ for (unsigned formati = 0; formati < format_count; ++formati) ++ { ++ unsigned lnct = read_uleb128 (format_ptr); ++ unsigned form = read_uleb128 (format_ptr); ++ bool handled_form = false; ++ bool handled_strp = false; ++ bool line_strp = form == DW_FORM_line_strp; ++ if (lnct == DW_LNCT_path) ++ { ++ switch (form) ++ { ++ case DW_FORM_strp: ++ case DW_FORM_line_strp: ++ if (dest_dir && phase == 0) ++ { ++ size_t idx = do_read_32_relocated (*ptrp); ++ if (record_file_string_entry_idx (line_strp, dso, idx)) ++ { ++ if (line_strp) ++ need_line_strp_update = true; ++ else ++ need_strp_update = true; ++ } ++ handled_strp = true; ++ if (collecting_dirs || writing_files) ++ { ++ debug_section *sec = &debug_sections[line_strp ++ ? DEBUG_LINE_STR : DEBUG_STR]; ++ if (collecting_dirs) ++ dir = (char *)sec->data + idx; ++ if (writing_files) ++ file = (char *)sec->data + idx; ++ } ++ } ++ break; ++ default: ++ error (0, 0, "%s: Unsupported " ++ ".debug_line %s %u path DW_FORM_0x%x", ++ dso->filename, entry_name, entryi, form); ++ return false; ++ } ++ } ++ if (writing_files && lnct == DW_LNCT_directory_index) ++ { ++ int dirndx; ++ switch (form) ++ { ++ case DW_FORM_udata: ++ handled_form = true; ++ dirndx = read_uleb128 (*ptrp); ++ break; ++ case DW_FORM_data1: ++ dirndx = **ptrp; ++ break; ++ case DW_FORM_data2: ++ dirndx = do_read_16 (*ptrp); ++ break; ++ case DW_FORM_data4: ++ dirndx = do_read_32 (*ptrp); ++ break; ++ default: ++ error (0, 0, "%s: Unsupported " ++ ".debug_line %s %u dirndx DW_FORM_0x%x", ++ dso->filename, entry_name, entryi, form); ++ return false; ++ } ++ ++ if (dirndx > *ndir) ++ { ++ error (0, 0, "%s: Bad dir number %u in .debug_line %s", ++ dso->filename, entryi, entry_name); ++ return false; ++ } ++ dir = (*dirs)[dirndx]; ++ } ++ ++ switch (form) ++ { ++ case DW_FORM_strp: ++ case DW_FORM_line_strp: ++ edit_strp (dso, line_strp, *ptrp, phase, handled_strp); ++ break; ++ } ++ ++ if (!handled_form) ++ { ++ switch (skip_form (dso, &form, ptrp)) ++ { ++ case FORM_OK: ++ break; ++ case FORM_ERROR: ++ return false; ++ case FORM_INDIRECT: ++ error (0, 0, "%s: Unsupported " ++ ".debug_line %s %u DW_FORM_indirect", ++ dso->filename, entry_name, entryi); ++ return false; ++ } ++ } ++ } ++ ++ if (collecting_dirs) ++ (*dirs)[entryi] = dir; ++ ++ if (writing_files) ++ { ++ char *comp_dir = (*dirs)[0]; ++ size_t comp_dir_len = strlen(comp_dir); ++ size_t file_len = strlen (file); ++ size_t dir_len = strlen (dir); ++ ++ char *s = malloc (comp_dir_len + 1 + file_len + 1 + dir_len + 1); ++ if (s == NULL) ++ { ++ error (0, ENOMEM, "%s: Reading file table", dso->filename); ++ return false; ++ } ++ if (file[0] == '/') ++ { ++ memcpy (s, file, file_len + 1); ++ } ++ else if (dir[0] == '/') ++ { ++ memcpy (s, dir, dir_len); ++ s[dir_len] = '/'; ++ memcpy (s + dir_len + 1, file, file_len + 1); ++ } ++ else ++ { ++ char *p = s; ++ if (comp_dir_len != 0) ++ { ++ memcpy (s, comp_dir, comp_dir_len); ++ s[comp_dir_len] = '/'; ++ p += comp_dir_len + 1; ++ } ++ memcpy (p, dir, dir_len); ++ p[dir_len] = '/'; ++ memcpy (p + dir_len + 1, file, file_len + 1); ++ } ++ canonicalize_path (s, s); ++ if (list_file_fd != -1) ++ { ++ const char *p = NULL; ++ if (base_dir == NULL) ++ p = s; ++ else ++ { ++ p = skip_dir_prefix (s, base_dir); ++ if (p == NULL && dest_dir != NULL) ++ p = skip_dir_prefix (s, dest_dir); ++ } ++ ++ if (p) ++ { ++ size_t size = strlen (p) + 1; ++ while (size > 0) ++ { ++ ssize_t ret = write (list_file_fd, p, size); ++ if (ret == -1) ++ break; ++ size -= ret; ++ p += ret; ++ } ++ } ++ } ++ ++ free (s); ++ } ++ } ++ ++ return true; ++} ++ ++/* Part of read_dwarf2_line processing DWARF-5. */ ++static bool ++read_dwarf5_line (DSO *dso, unsigned char *ptr, struct line_table *table, ++ int phase) ++{ ++ char **dirs = NULL; ++ int ndir; ++ /* Skip header. */ ++ ptr += (4 /* unit len */ ++ + 2 /* version */ ++ + (table->version < 5 ? 0 : 0 ++ + 1 /* address_size */ ++ + 1 /* segment_selector*/) ++ + 4 /* header len */ ++ + 1 /* min instr len */ ++ + (table->version >= 4) /* max op per instr, if version >= 4 */ ++ + 1 /* default is stmt */ ++ + 1 /* line base */ ++ + 1 /* line range */ ++ + 1 /* opcode base */ ++ + table->opcode_base - 1); /* opcode len table */ ++ ++ bool retval = (read_dwarf5_line_entries (dso, &ptr, table, phase, ++ &dirs, &ndir, "directory") ++ && read_dwarf5_line_entries (dso, &ptr, table, phase, ++ &dirs, &ndir, "file name")); ++ free (dirs); ++ return retval; ++} ++ + /* Called during phase zero for each debug_line table referenced from + .debug_info. Outputs all source files seen and records any + adjustments needed in the debug_list data structures. Returns true +@@ -1778,6 +2057,9 @@ read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir) + ptr = debug_sections[DEBUG_LINE].data + off; + ptr += (4 /* unit len */ + + 2 /* version */ ++ + (table->version < 5 ? 0 : 0 ++ + 1 /* address_size */ ++ + 1 /* segment_selector*/) + + 4 /* header len */ + + 1 /* min instr len */ + + (table->version >= 4) /* max op per instr, if version >= 4 */ +@@ -1787,8 +2069,13 @@ read_dwarf2_line (DSO *dso, uint32_t off, char *comp_dir) + + 1 /* opcode base */ + + table->opcode_base - 1); /* opcode len table */ + +- if (! read_dwarf4_line (dso, ptr, comp_dir, table)) +- return false; ++ /* DWARF version 5 line tables won't change size. But they might need ++ [line]strp recording/updates. Handle that part later. */ ++ if (table->version < 5) ++ { ++ if (! read_dwarf4_line (dso, ptr, comp_dir, table)) ++ return false; ++ } + + dso->lines.debug_lines_len += 4 + table->unit_length + table->size_diff; + return table->replace_dirs || table->replace_files; +@@ -1807,20 +2094,22 @@ find_new_list_offs (struct debug_lines *lines, size_t idx) + return table->new_idx; + } + +-/* Read DW_FORM_strp collecting compilation directory. */ ++/* Read DW_FORM_strp or DW_FORM_line_strp collecting compilation directory. */ + static void +-edit_attributes_str_comp_dir (DSO *dso, unsigned char **ptrp, int phase, +- char **comp_dirp, bool *handled_strpp) ++edit_attributes_str_comp_dir (bool line_strp, DSO *dso, unsigned char **ptrp, ++ int phase, char **comp_dirp, bool *handled_strpp) + { + const char *dir; + size_t idx = do_read_32_relocated (*ptrp); + /* In phase zero we collect the comp_dir. */ + if (phase == 0) + { +- if (idx >= debug_sections[DEBUG_STR].size) +- error (1, 0, "%s: Bad string pointer index %zd for comp_dir", +- dso->filename, idx); +- dir = (char *) debug_sections[DEBUG_STR].data + idx; ++ debug_section *sec = &debug_sections[line_strp ++ ? DEBUG_LINE_STR : DEBUG_STR]; ++ if (sec->data == NULL || idx >= sec->size) ++ error (1, 0, "%s: Bad string pointer index %zd for comp_dir (%s)", ++ dso->filename, idx, sec->name); ++ dir = (char *) sec->data + idx; + + free (*comp_dirp); + *comp_dirp = strdup (dir); +@@ -1828,8 +2117,13 @@ edit_attributes_str_comp_dir (DSO *dso, unsigned char **ptrp, int phase, + + if (dest_dir != NULL && phase == 0) + { +- if (record_file_string_entry_idx (&dso->strings, idx)) +- need_strp_update = true; ++ if (record_file_string_entry_idx (line_strp, dso, idx)) ++ { ++ if (line_strp) ++ need_line_strp_update = true; ++ else ++ need_strp_update = true; ++ } + *handled_strpp = true; + } + } +@@ -1937,17 +2231,24 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) + } + } + } +- else if (form == DW_FORM_strp && +- debug_sections[DEBUG_STR].data) +- edit_attributes_str_comp_dir (dso, &ptr, phase, &comp_dir, ++ else if (form == DW_FORM_strp) ++ edit_attributes_str_comp_dir (false /* line_strp */, dso, ++ &ptr, phase, &comp_dir, + &handled_strp); ++ else if (form == DW_FORM_line_strp) ++ edit_attributes_str_comp_dir (true /* line_strp */, dso, &ptr, ++ phase, &comp_dir, &handled_strp); + } + else if ((t->tag == DW_TAG_compile_unit + || t->tag == DW_TAG_partial_unit) +- && t->attr[i].attr == DW_AT_name +- && form == DW_FORM_strp +- && debug_sections[DEBUG_STR].data) ++ && ((form == DW_FORM_strp ++ && debug_sections[DEBUG_STR].data) ++ || (form == DW_FORM_line_strp ++ && debug_sections[DEBUG_LINE_STR].data)) ++ && t->attr[i].attr == DW_AT_name) + { ++ bool line_strp = form == DW_FORM_line_strp; ++ + /* DW_AT_name is the primary file for this compile + unit. If starting with / it is a full path name. + Note that we don't handle DW_FORM_string in this +@@ -1957,11 +2258,14 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) + /* In phase zero we will look for a comp_dir to use. */ + if (phase == 0) + { +- if (idx >= debug_sections[DEBUG_STR].size) ++ debug_section *sec = &debug_sections[line_strp ++ ? DEBUG_LINE_STR ++ : DEBUG_STR]; ++ if (idx >= sec->size) + error (1, 0, +- "%s: Bad string pointer index %zd for unit name", +- dso->filename, idx); +- char *name = (char *) debug_sections[DEBUG_STR].data + idx; ++ "%s: Bad string pointer index %zd for unit name (%s)", ++ dso->filename, idx, sec->name); ++ char *name = (char *) sec->data + idx; + if (*name == '/' && comp_dir == NULL) + { + char *enddir = strrchr (name, '/'); +@@ -1982,8 +2286,13 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) + pass (1) stores it (the new index). */ + if (dest_dir && phase == 0) + { +- if (record_file_string_entry_idx (&dso->strings, idx)) +- need_strp_update = true; ++ if (record_file_string_entry_idx (line_strp, dso, idx)) ++ { ++ if (line_strp) ++ need_line_strp_update = true; ++ else ++ need_strp_update = true; ++ } + handled_strp = true; + } + } +@@ -1991,7 +2300,10 @@ edit_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, int phase) + switch (form) + { + case DW_FORM_strp: +- edit_strp (dso, ptr, phase, handled_strp); ++ edit_strp (dso, false /* line_strp */, ptr, phase, handled_strp); ++ break; ++ case DW_FORM_line_strp: ++ edit_strp (dso, true /* line_strp */, ptr, phase, handled_strp); + break; + } + +@@ -2196,11 +2508,11 @@ edit_info (DSO *dso, int phase, struct debug_section *sec) + + /* Rebuild .debug_str. */ + static void +-edit_dwarf2_any_str (DSO *dso) ++edit_dwarf2_any_str (DSO *dso, struct strings *strings, debug_section *secp) + { +- Strtab *strtab = dso->strings.str_tab; +- Elf_Data *strdata = debug_sections[DEBUG_STR].elf_data; +- int strndx = debug_sections[DEBUG_STR].sec; ++ Strtab *strtab = strings->str_tab; ++ Elf_Data *strdata = secp->elf_data; ++ int strndx = secp->sec; + Elf_Scn *strscn = dso->scn[strndx]; + + /* Out with the old. */ +@@ -2212,8 +2524,8 @@ edit_dwarf2_any_str (DSO *dso) + but the old ebl version will just abort on out of + memory... */ + strtab_finalize (strtab, strdata); +- debug_sections[DEBUG_STR].size = strdata->d_size; +- dso->strings.str_buf = strdata->d_buf; ++ secp->size = strdata->d_size; ++ strings->str_buf = strdata->d_buf; + } + + static int +@@ -2359,12 +2671,14 @@ edit_dwarf2 (DSO *dso) + bool info_rel_updated = false; + bool types_rel_updated = false; + bool macro_rel_updated = false; ++ bool line_rel_updated = false; + + for (phase = 0; phase < 2; phase++) + { + /* If we don't need to update anyhing, skip phase 1. */ + if (phase == 1 + && !need_strp_update ++ && !need_line_strp_update + && !need_string_replacement + && !need_stmt_update) + break; +@@ -2582,15 +2896,14 @@ edit_dwarf2 (DSO *dso) + if (phase == 0) + { + size_t idx = read_32_relocated (ptr); +- record_existing_string_entry_idx (&dso->strings, +- idx); ++ record_existing_string_entry_idx (false, dso, idx); + } + else + { + struct stridxentry *entry; + size_t idx, new_idx; + idx = do_read_32_relocated (ptr); +- entry = string_find_entry (&dso->strings, idx); ++ entry = string_find_entry (&dso->debug_str, idx); + new_idx = strent_offset (entry->entry); + write_32_relocated (ptr, new_idx); + } +@@ -2610,24 +2923,50 @@ edit_dwarf2 (DSO *dso) + } + } + +- /* Same for the debug_str section. Make sure everything is +- in place for phase 1 updating of debug_info ++ ++ /* Now handle all the DWARF5 line tables, they contain strp ++ and/or line_strp entries that need to be registered/rewritten. */ ++ setup_relbuf(dso, &debug_sections[DEBUG_LINE], &reltype); ++ rel_updated = false; ++ ++ /* edit_dwarf2_line will have set this up, unless there are no ++ moved/resized (DWARF4) lines. In which case we can just use ++ the original section data. new_idx will have been setup ++ correctly, even if it is the same as old_idx. */ ++ unsigned char *line_buf = (unsigned char *)dso->lines.line_buf; ++ if (line_buf == NULL) ++ line_buf = debug_sections[DEBUG_LINE].data; ++ for (int ldx = 0; ldx < dso->lines.used; ldx++) ++ { ++ struct line_table *t = &dso->lines.table[ldx]; ++ if (t->version >= 5) ++ read_dwarf5_line (dso, line_buf + t->new_idx, t, phase); ++ } ++ if (rel_updated) ++ line_rel_updated = true; ++ ++ /* Same for the debug_str and debug_line_str sections. ++ Make sure everything is in place for phase 1 updating of debug_info + references. */ + if (phase == 0 && need_strp_update) +- edit_dwarf2_any_str (dso); +- ++ edit_dwarf2_any_str (dso, &dso->debug_str, ++ &debug_sections[DEBUG_STR]); ++ if (phase == 0 && need_line_strp_update) ++ edit_dwarf2_any_str (dso, &dso->debug_line_str, ++ &debug_sections[DEBUG_LINE_STR]); + } + + /* After phase 1 we might have rewritten the debug_info with + new strp, strings and/or linep offsets. */ +- if (need_strp_update || need_string_replacement || need_stmt_update) { ++ if (need_strp_update || need_line_strp_update ++ || need_string_replacement || need_stmt_update) { + dirty_section (DEBUG_INFO); + if (debug_sections[DEBUG_TYPES].data != NULL) + dirty_section (DEBUG_TYPES); + } + if (need_strp_update || need_stmt_update) + dirty_section (DEBUG_MACRO); +- if (need_stmt_update) ++ if (need_stmt_update || need_line_strp_update) + dirty_section (DEBUG_LINE); + + /* Update any relocations addends we might have touched. */ +@@ -2653,6 +2992,9 @@ edit_dwarf2 (DSO *dso) + } + } + ++ if (line_rel_updated) ++ update_rela_data (dso, &debug_sections[DEBUG_LINE]); ++ + return 0; + } + +@@ -2745,7 +3087,8 @@ fdopen_dso (int fd, const char *name) + } + + dso->filename = (const char *) strdup (name); +- setup_strings (&dso->strings); ++ setup_strings (&dso->debug_str); ++ setup_strings (&dso->debug_line_str); + setup_lines (&dso->lines); + return dso; + +@@ -2753,7 +3096,8 @@ error_out: + if (dso) + { + free ((char *) dso->filename); +- destroy_strings (&dso->strings); ++ destroy_strings (&dso->debug_str); ++ destroy_strings (&dso->debug_line_str); + destroy_lines (&dso->lines); + free (dso); + } +@@ -3034,7 +3378,9 @@ main (int argc, char *argv[]) + in elfutils before 0.169 we will have to update and write out all + section data if any data has changed (when ELF_F_LAYOUT was + set). https://sourceware.org/bugzilla/show_bug.cgi?id=21199 */ +- bool need_update = need_strp_update || need_stmt_update; ++ bool need_update = (need_strp_update ++ || need_line_strp_update ++ || need_stmt_update); + + #if !_ELFUTILS_PREREQ (0, 169) + /* string replacements or build_id updates don't change section size. */ +@@ -3106,10 +3452,12 @@ main (int argc, char *argv[]) + GElf_Xword sec_size = shdr->sh_size; + + /* We might have changed the size (and content) of the +- debug_str or debug_line section. */ ++ debug_str, debug_line_str or debug_line section. */ + size_t secnum = elf_ndxscn (scn); + if (secnum == debug_sections[DEBUG_STR].sec) + sec_size = debug_sections[DEBUG_STR].size; ++ if (secnum == debug_sections[DEBUG_LINE_STR].sec) ++ sec_size = debug_sections[DEBUG_LINE_STR].size; + if (secnum == debug_sections[DEBUG_LINE].sec) + sec_size = debug_sections[DEBUG_LINE].size; + +@@ -3179,7 +3527,8 @@ main (int argc, char *argv[]) + chmod (file, stat_buf.st_mode); + + free ((char *) dso->filename); +- destroy_strings (&dso->strings); ++ destroy_strings (&dso->debug_str); ++ destroy_strings (&dso->debug_line_str); + destroy_lines (&dso->lines); + free (dso); + +-- +2.18.4 + diff --git a/SOURCES/rpm-4.12.0-rpm2cpio-hack.patch b/SOURCES/rpm-4.12.0-rpm2cpio-hack.patch new file mode 100644 index 0000000..38c7dbd --- /dev/null +++ b/SOURCES/rpm-4.12.0-rpm2cpio-hack.patch @@ -0,0 +1,18 @@ +diff --git a/rpm2cpio.c b/rpm2cpio.c +index 89ebdfa..ae999ff 100644 +--- a/rpm2cpio.c ++++ b/rpm2cpio.c +@@ -84,7 +84,12 @@ int main(int argc, char *argv[]) + exit(EXIT_FAILURE); + } + +- rc = (ufdCopy(gzdi, fdo) == payload_size) ? EXIT_SUCCESS : EXIT_FAILURE; ++ /* ++ * XXX HACK for #1142949: should be equality test, but archive size ++ * short by cpio trailer size in packages built with rpm 4.12.0 ++ * and its pre-releases. ++ */ ++ rc = (ufdCopy(gzdi, fdo) >= payload_size) ? EXIT_SUCCESS : EXIT_FAILURE; + + Fclose(fdo); + diff --git a/SOURCES/rpm-4.15.x-ldflags.patch b/SOURCES/rpm-4.15.x-ldflags.patch new file mode 100644 index 0000000..c781ca8 --- /dev/null +++ b/SOURCES/rpm-4.15.x-ldflags.patch @@ -0,0 +1,15 @@ +diff -up rpm-4.9.1.1/macros.in.jx rpm-4.9.1.1/macros.in +--- rpm-4.9.1.1/macros.in.jx 2011-08-03 16:19:05.000000000 -0400 ++++ rpm-4.9.1.1/macros.in 2011-08-08 09:41:52.981064316 -0400 +@@ -674,9 +674,10 @@ print (t)\ + RPM_BUILD_DIR=\"%{u2p:%{_builddir}}\"\ + RPM_OPT_FLAGS=\"%{optflags}\"\ ++ RPM_LD_FLAGS=\"%{?build_ldflags}\"\ + RPM_ARCH=\"%{_arch}\"\ + RPM_OS=\"%{_os}\"\ + RPM_BUILD_NCPUS=\"%{_smp_build_ncpus}\"\ +- export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_ARCH RPM_OS RPM_BUILD_NCPUS\ ++ export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_LD_FLAGS RPM_ARCH RPM_OS RPM_BUILD_NCPUS RPM_LD_FLAGS\ + RPM_DOC_DIR=\"%{_docdir}\"\ + export RPM_DOC_DIR\ + RPM_PACKAGE_NAME=\"%{NAME}\"\ diff --git a/SOURCES/rpm-4.15.x-siteconfig.patch b/SOURCES/rpm-4.15.x-siteconfig.patch new file mode 100644 index 0000000..5df41d4 --- /dev/null +++ b/SOURCES/rpm-4.15.x-siteconfig.patch @@ -0,0 +1,12 @@ +diff -up rpm-4.11.1-rc1/macros.in.siteconfig rpm-4.11.1-rc1/macros.in +--- rpm-4.11.1-rc1/macros.in.siteconfig 2013-06-07 13:19:21.000000000 +0300 ++++ rpm-4.11.1-rc1/macros.in 2013-06-11 15:06:59.525747503 +0300 +@@ -647,6 +647,8 @@ package or when debugging this package.\ + export CLASSPATH}\ + PKG_CONFIG_PATH=\"${PKG_CONFIG_PATH}:%{_libdir}/pkgconfig:%{_datadir}/pkgconfig\"\ + export PKG_CONFIG_PATH\ ++ CONFIG_SITE=${CONFIG_SITE:-NONE}\ ++ export CONFIG_SITE\ + \ + %{verbose:set -x}\ + umask 022\ diff --git a/SOURCES/rpm-4.16.1.3-ELF-files-strip-when-debuginfo-disabled.patch b/SOURCES/rpm-4.16.1.3-ELF-files-strip-when-debuginfo-disabled.patch new file mode 100644 index 0000000..70c2a0b --- /dev/null +++ b/SOURCES/rpm-4.16.1.3-ELF-files-strip-when-debuginfo-disabled.patch @@ -0,0 +1,36 @@ +From 7f0b7217fb1c20ec6ce0c0e0bfee0349f27a2511 Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Fri, 8 Jan 2021 13:59:59 +0200 +Subject: [PATCH] Ensure ELF files get stripped when debuginfo is disabled + +Depending on libmagic version, PIE executables can be reported as +"shared object" avoiding the strip. And so will any libraries because +we're explicitly skipping them for whatever historical reason - perhaps +because there's a separate script for stripping the libraries, but that +has been never enabled in rpm, and relying on "file" strings to do this +is hopelessly unreliable. + +Also drop file permissions checks: making shared libraries executable +just to have them stripped is not sensical, especially in the light of +commit 80818e4f902ba3cf85e4cfcd8a7a4c71c601f3cf + +Reported once upon time as RhBug:988812 and later RhBug:1634084 +--- + scripts/brp-strip | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/scripts/brp-strip b/scripts/brp-strip +index c3484fe3c..35fbb593a 100755 +--- a/scripts/brp-strip ++++ b/scripts/brp-strip +@@ -13,5 +13,5 @@ Darwin*) exit 0 ;; + esac + + # Strip ELF binaries +-find "$RPM_BUILD_ROOT" -type f \( -perm -0100 -or -perm -0010 -or -perm -0001 \) \! -regex "${RPM_BUILD_ROOT}/*usr/lib/debug.*" -print0 | \ +- xargs -0 -r -P$NCPUS -n32 sh -c "file \"\$@\" | grep -v ' shared object,' | sed -n -e 's/^\(.*\):[ ]*ELF.*, not stripped.*/\1/p' | xargs -I\{\} $STRIP -g \{\}" ARG0 ++find "$RPM_BUILD_ROOT" -type f \! -regex "${RPM_BUILD_ROOT}/*usr/lib/debug.*" -print0 | \ ++ xargs -0 -r -P$NCPUS -n32 sh -c "file \"\$@\" | sed -n -e 's/^\(.*\):[ ]*ELF.*, not stripped.*/\1/p' | xargs -I\{\} $STRIP -g \{\}" ARG0 +-- +2.33.1 + diff --git a/SOURCES/rpm-4.16.1.3-add-fapolicyd-plugin.patch b/SOURCES/rpm-4.16.1.3-add-fapolicyd-plugin.patch new file mode 100644 index 0000000..33aef5a --- /dev/null +++ b/SOURCES/rpm-4.16.1.3-add-fapolicyd-plugin.patch @@ -0,0 +1,334 @@ +commit 39595ccee321497dc3b08c7cab8a10304345429c +Author: Radovan Sroka +Date: Tue Oct 27 16:18:04 2020 +0100 + + Added fapolicyd rpm plugin + + Fapolicyd (File Access Policy Daemon) implements application whitelisting + to decide file access rights. Applications that are known via a reputation + source are allowed access while unknown applications are not. + + The rpm plugin allows us to use rpm database as a source of trust. + We used dnf plugin since the beggining but it only provides notification + when transaction ends. With "integrity checking" requirement we need + a continual addition of files which are installed during the system + update. With fapolicyd rpm plugin we can allow using of recently + added/updated files in scriptlets during rpm transaction. + + The fapolicyd plugin gathers metadata of currently installed files. + It sends the information about files and about ongoing rpm transaction + to the fapolicyd daemon. The information is written to Linux pipe which + is placed in /var/run/fapolicyd/fapolicyd.fifo. + + The data format is "%s %lu %64s\n". [path, size, sha256] + + The fapolicyd rpm plugin can be enabled with "--with-fapolicyd" + configure option. + + Related PRs: + https://github.com/linux-application-whitelisting/fapolicyd/pull/105 + https://github.com/linux-application-whitelisting/fapolicyd/pull/106 + + Signed-off-by: Radovan Sroka + + Backported into 4.16.1.3, together with commit + 6d61b7118adcc14631b7ee5163a481472af940b8 (covscan fix) + +diff -up rpm-4.16.1.3/configure.ac.orig rpm-4.16.1.3/configure.ac +--- rpm-4.16.1.3/configure.ac.orig 2021-03-22 11:05:07.311635968 +0100 ++++ rpm-4.16.1.3/configure.ac 2021-07-22 16:18:29.352006782 +0200 +@@ -891,6 +891,14 @@ AS_IF([test "$enable_plugins" != no],[ + AM_CONDITIONAL(IMA, [test "x$ac_cv_func_lsetxattr" = xyes]) + + #================= ++# Check for fapolicyd support ++AC_ARG_WITH(fapolicyd, ++AS_HELP_STRING([--with-fapolicyd],[build with File Access Policy Daemon support]), ++with_fapolicyd=$withval, ++with_fapolicyd=auto) ++AM_CONDITIONAL(FAPOLICYD,[test "$with_fapolicyd" = yes]) ++ ++#================= + # Check for audit library. + AC_ARG_WITH(audit, + AS_HELP_STRING([--with-audit],[Linux audit plugin]), +diff -up rpm-4.16.1.3/doc/Makefile.am.orig rpm-4.16.1.3/doc/Makefile.am +--- rpm-4.16.1.3/doc/Makefile.am.orig 2020-06-23 14:13:01.895628382 +0200 ++++ rpm-4.16.1.3/doc/Makefile.am 2021-07-22 16:18:29.352006782 +0200 +@@ -25,6 +25,9 @@ endif + if IMA + man_man8_DATA += rpm-plugin-ima.8 + endif ++if FAPOLICYD ++man_man8_DATA += rpm-plugin-fapolicyd.8 ++endif + if SELINUX + man_man8_DATA += rpm-plugin-selinux.8 + endif +@@ -37,6 +40,8 @@ endif + EXTRA_DIST += rpm-plugins.8 rpm-plugin-prioreset.8 rpm-plugin-syslog.8 + EXTRA_DIST += rpm-plugin-audit.8 rpm-plugin-systemd-inhibit.8 + EXTRA_DIST += rpm-plugin-ima.8 rpm-plugin-selinux.8 rpm2archive.8 ++EXTRA_DIST += rpm-plugin-fapolicyd.8 ++ + + man_fr_man8dir = $(mandir)/fr/man8 + man_fr_man8_DATA = fr/rpm.8 +diff -up rpm-4.16.1.3/doc/rpm-plugin-fapolicyd.8.orig rpm-4.16.1.3/doc/rpm-plugin-fapolicyd.8 +--- rpm-4.16.1.3/doc/rpm-plugin-fapolicyd.8.orig 2021-07-22 16:18:29.353006800 +0200 ++++ rpm-4.16.1.3/doc/rpm-plugin-fapolicyd.8 2021-07-22 16:18:29.353006800 +0200 +@@ -0,0 +1,21 @@ ++'\" t ++.TH "RPM-FAPOLICYD" "8" "28 Jan 2021" "Red Hat, Inc." ++.SH NAME ++rpm-plugin-fapolicyd \- Fapolicyd plugin for the RPM Package Manager ++ ++.SH Description ++ ++The plugin gathers metadata of currently installed files. It sends the ++information about files and about ongoing rpm transaction to the fapolicyd daemon. ++The information is written to Linux pipe which is placed in ++/var/run/fapolicyd/fapolicyd.fifo. ++ ++.SH Configuration ++ ++There are currently no options for this plugin in particular. See ++.BR rpm-plugins (8) ++on how to control plugins in general. ++ ++.SH SEE ALSO ++.IR fapolicyd (8) ++.IR rpm-plugins (8) +diff -up rpm-4.16.1.3/macros.in.orig rpm-4.16.1.3/macros.in +--- rpm-4.16.1.3/macros.in.orig 2021-07-22 16:18:20.525844141 +0200 ++++ rpm-4.16.1.3/macros.in 2021-07-22 16:19:36.196238525 +0200 +@@ -1208,6 +1208,7 @@ package or when debugging this package.\ + %__transaction_selinux %{__plugindir}/selinux.so + %__transaction_syslog %{__plugindir}/syslog.so + %__transaction_ima %{__plugindir}/ima.so ++%__transaction_fapolicyd %{__plugindir}/fapolicyd.so + %__transaction_prioreset %{__plugindir}/prioreset.so + %__transaction_audit %{__plugindir}/audit.so + +diff -up rpm-4.16.1.3/Makefile.am.orig rpm-4.16.1.3/Makefile.am +--- rpm-4.16.1.3/Makefile.am.orig 2021-07-22 16:18:29.350006745 +0200 ++++ rpm-4.16.1.3/Makefile.am 2021-07-22 16:19:18.223907346 +0200 +@@ -14,6 +14,7 @@ DISTCHECK_CONFIGURE_FLAGS = \ + --with-audit \ + --with-selinux \ + --with-imaevm \ ++ --with-fapolicyd \ + --disable-dependency-tracking + + include $(top_srcdir)/rpm.am +diff -up rpm-4.16.1.3/plugins/fapolicyd.c.orig rpm-4.16.1.3/plugins/fapolicyd.c +--- rpm-4.16.1.3/plugins/fapolicyd.c.orig 2021-07-22 16:18:29.356006855 +0200 ++++ rpm-4.16.1.3/plugins/fapolicyd.c 2021-07-22 16:18:35.380117862 +0200 +@@ -0,0 +1,191 @@ ++#include "system.h" ++ ++#include ++#include ++#include "lib/rpmplugin.h" ++ ++#include ++#include ++#include ++#include ++ ++struct fapolicyd_data { ++ int fd; ++ long changed_files; ++ const char * fifo_path; ++}; ++ ++static struct fapolicyd_data fapolicyd_state = { ++ .fd = -1, ++ .changed_files = 0, ++ .fifo_path = "/run/fapolicyd/fapolicyd.fifo", ++}; ++ ++static rpmRC open_fifo(struct fapolicyd_data* state) ++{ ++ int fd = -1; ++ struct stat s; ++ ++ fd = open(state->fifo_path, O_RDWR); ++ if (fd == -1) { ++ rpmlog(RPMLOG_DEBUG, "Open: %s -> %s\n", state->fifo_path, strerror(errno)); ++ goto bad; ++ } ++ ++ if (stat(state->fifo_path, &s) == -1) { ++ rpmlog(RPMLOG_DEBUG, "Stat: %s -> %s\n", state->fifo_path, strerror(errno)); ++ goto bad; ++ } ++ ++ if (!S_ISFIFO(s.st_mode)) { ++ rpmlog(RPMLOG_DEBUG, "File: %s exists but it is not a pipe!\n", state->fifo_path); ++ goto bad; ++ } ++ ++ /* keep only file's permition bits */ ++ mode_t mode = s.st_mode & ~S_IFMT; ++ ++ /* we require pipe to have 0660 permission */ ++ if (mode != 0660) { ++ rpmlog(RPMLOG_ERR, "File: %s has %o instead of 0660 \n", ++ state->fifo_path, ++ mode ); ++ goto bad; ++ } ++ ++ state->fd = fd; ++ /* considering success */ ++ return RPMRC_OK; ++ ++ bad: ++ if (fd >= 0) ++ close(fd); ++ return RPMRC_FAIL; ++} ++ ++static rpmRC write_fifo(struct fapolicyd_data* state, const char * str) ++{ ++ ssize_t len = strlen(str); ++ ssize_t written = 0; ++ ssize_t n = 0; ++ ++ while (written < len) { ++ if ((n = write(state->fd, str + written, len - written)) < 0) { ++ if (errno == EINTR || errno == EAGAIN) ++ continue; ++ rpmlog(RPMLOG_DEBUG, "Write: %s -> %s\n", state->fifo_path, strerror(errno)); ++ goto bad; ++ } ++ written += n; ++ } ++ ++ return RPMRC_OK; ++ ++ bad: ++ return RPMRC_FAIL; ++} ++ ++static rpmRC fapolicyd_init(rpmPlugin plugin, rpmts ts) ++{ ++ if (rpmtsFlags(ts) & (RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_BUILD_PROBS)) ++ goto end; ++ ++ if (!rstreq(rpmtsRootDir(ts), "/")) ++ goto end; ++ ++ (void) open_fifo(&fapolicyd_state); ++ ++ end: ++ return RPMRC_OK; ++} ++ ++static void fapolicyd_cleanup(rpmPlugin plugin) ++{ ++ if (fapolicyd_state.fd > 0) ++ (void) close(fapolicyd_state.fd); ++ ++ fapolicyd_state.fd = -1; ++} ++ ++static rpmRC fapolicyd_tsm_post(rpmPlugin plugin, rpmts ts, int res) ++{ ++ if (rpmtsFlags(ts) & (RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_BUILD_PROBS)) ++ goto end; ++ ++ /* we are ready */ ++ if (fapolicyd_state.fd > 0) { ++ /* send a signal that transaction is over */ ++ (void) write_fifo(&fapolicyd_state, "1\n"); ++ /* flush cache */ ++ (void) write_fifo(&fapolicyd_state, "2\n"); ++ } ++ ++ end: ++ return RPMRC_OK; ++} ++ ++static rpmRC fapolicyd_scriptlet_pre(rpmPlugin plugin, const char *s_name, ++ int type) ++{ ++ if (fapolicyd_state.fd == -1) ++ goto end; ++ ++ if (fapolicyd_state.changed_files > 0) { ++ /* send signal to flush cache */ ++ (void) write_fifo(&fapolicyd_state, "2\n"); ++ ++ /* optimize flushing */ ++ /* flush only when there was an actual change */ ++ fapolicyd_state.changed_files = 0; ++ } ++ ++ end: ++ return RPMRC_OK; ++} ++ ++static rpmRC fapolicyd_fsm_file_prepare(rpmPlugin plugin, rpmfi fi, ++ const char *path, const char *dest, ++ mode_t file_mode, rpmFsmOp op) ++{ ++ /* not ready */ ++ if (fapolicyd_state.fd == -1) ++ goto end; ++ ++ rpmFileAction action = XFO_ACTION(op); ++ ++ /* Ignore skipped files and unowned directories */ ++ if (XFA_SKIPPING(action) || (op & FAF_UNOWNED)) { ++ rpmlog(RPMLOG_DEBUG, "fapolicyd skipping early: path %s dest %s\n", ++ path, dest); ++ goto end; ++ } ++ ++ if (!S_ISREG(rpmfiFMode(fi))) { ++ rpmlog(RPMLOG_DEBUG, "fapolicyd skipping non regular: path %s dest %s\n", ++ path, dest); ++ goto end; ++ } ++ ++ fapolicyd_state.changed_files++; ++ ++ char buffer[4096]; ++ ++ rpm_loff_t size = rpmfiFSize(fi); ++ char * sha = rpmfiFDigestHex(fi, NULL); ++ ++ snprintf(buffer, 4096, "%s %lu %64s\n", dest, size, sha); ++ (void) write_fifo(&fapolicyd_state, buffer); ++ ++ free(sha); ++ ++ end: ++ return RPMRC_OK; ++} ++ ++struct rpmPluginHooks_s fapolicyd_hooks = { ++ .init = fapolicyd_init, ++ .cleanup = fapolicyd_cleanup, ++ .scriptlet_pre = fapolicyd_scriptlet_pre, ++ .tsm_post = fapolicyd_tsm_post, ++ .fsm_file_prepare = fapolicyd_fsm_file_prepare, ++}; +diff -up rpm-4.16.1.3/plugins/Makefile.am.orig rpm-4.16.1.3/plugins/Makefile.am +--- rpm-4.16.1.3/plugins/Makefile.am.orig 2021-07-22 16:18:23.022890155 +0200 ++++ rpm-4.16.1.3/plugins/Makefile.am 2021-07-22 16:18:55.797494098 +0200 +@@ -43,6 +43,12 @@ ima_la_LIBADD = $(top_builddir)/lib/libr + plugins_LTLIBRARIES += ima.la + endif + ++if FAPOLICYD ++fapolicyd_la_sources = fapolicyd.c ++fapolicyd_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/librpmio.la ++plugins_LTLIBRARIES += fapolicyd.la ++endif ++ + if AUDIT + audit_la_sources = audit.c + audit_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/librpmio.la @WITH_AUDIT_LIB@ diff --git a/SOURCES/rpm-4.16.1.3-add-path-query-option.patch b/SOURCES/rpm-4.16.1.3-add-path-query-option.patch new file mode 100644 index 0000000..324f098 --- /dev/null +++ b/SOURCES/rpm-4.16.1.3-add-path-query-option.patch @@ -0,0 +1,197 @@ +From ba659220886c1a315f50fb91b9af4615b1a8757e Mon Sep 17 00:00:00 2001 +From: Michal Domonkos +Date: Mon, 16 Aug 2021 18:21:02 +0200 +Subject: [PATCH] Add support for RPMDBI_BASENAMES on file queries + +There are legitimate reasons (such as rhbz#1940895 or the included test) +for wanting the former behavior where all file states were considered in +file queries prior to commit 9ad57bda4a82b9847826daa766b4421d877bb3d9, +so celebrate the tenth anniversary of that commit by adding a CLI switch +(a new package selector --path), as contemplated back then. + +Update the man page for --file to reflect it's current behavior and make +--path that more obvious. + +Resolves: rhbz#1940895 + +Combined with: +d1aebda01033bc8ba0d748b49f6fad9a5c0caa3f +f62b6d27cd741406a52a7e9c5b1d6f581dbd3af8 + +Backported for 4.16.1.3. +--- + doc/rpm.8 | 9 ++++++-- + lib/poptQV.c | 6 +++++- + lib/query.c | 7 +++++-- + lib/rpmcli.h | 1 + + tests/rpmquery.at | 52 +++++++++++++++++++++++++++++++++++++++++++++++ + 5 files changed, 70 insertions(+), 5 deletions(-) + +diff --git a/doc/rpm.8 b/doc/rpm.8 +index 80055b675..ab7364cf6 100644 +--- a/doc/rpm.8 ++++ b/doc/rpm.8 +@@ -57,7 +57,7 @@ rpm \- RPM Package Manager + .PP + + [\fB\fIPACKAGE_NAME\fB\fR] +- [\fB-a,--all [\fISELECTOR\fR]\fR] [\fB-f,--file \fIFILE\fB\fR] ++ [\fB-a,--all [\fISELECTOR\fR]\fR] [\fB-f,--file \fIFILE\fB\fR] [\fB--path \fIPATH\fB\fR] + [\fB-g,--group \fIGROUP\fB\fR] [\fB-p,--package \fIPACKAGE_FILE\fB\fR] + [\fB--hdrid \fISHA1\fB\fR] [\fB--pkgid \fIMD5\fB\fR] [\fB--tid \fITID\fB\fR] + [\fB--querybynumber \fIHDRNUM\fB\fR] [\fB--triggeredby \fIPACKAGE_NAME\fB\fR] +@@ -569,7 +569,7 @@ starts with "b". + List duplicated packages. + .TP + \fB-f, --file \fIFILE\fB\fR +-Query package owning \fIFILE\fR. ++Query package owning installed \fIFILE\fR. + .TP + \fB--filecaps\fR + List file names with POSIX1.e capabilities. +@@ -612,6 +612,11 @@ that will be expanded to paths that are substituted in place of + the package manifest as additional \fIPACKAGE_FILE\fR + arguments to the query. + .TP ++\fB--path \fIPATH\fB\fR ++Query package(s) owning \fIPATH\fR, whether the file is installed or not. ++Multiple packages may own a \fIPATH\fR, but the file is only owned by the ++package installed last. ++.TP + \fB--pkgid \fIMD5\fB\fR + Query package that contains a given package identifier, i.e. the + \fIMD5\fR digest of the combined header and +diff --git a/lib/poptQV.c b/lib/poptQV.c +index d9d1fad75..9b6101009 100644 +--- a/lib/poptQV.c ++++ b/lib/poptQV.c +@@ -27,6 +27,7 @@ struct rpmQVKArguments_s rpmQVKArgs; + #define POPT_WHATENHANCES -1014 + #define POPT_WHATOBSOLETES -1015 + #define POPT_WHATCONFLICTS -1016 ++#define POPT_QUERYBYPATH -1017 + + /* ========== Query/Verify/Signature source args */ + static void rpmQVSourceArgCallback( poptContext con, +@@ -58,6 +59,7 @@ static void rpmQVSourceArgCallback( poptContext con, + case POPT_WHATSUPPLEMENTS: qva->qva_source |= RPMQV_WHATSUPPLEMENTS; break; + case POPT_WHATENHANCES: qva->qva_source |= RPMQV_WHATENHANCES; break; + case POPT_TRIGGEREDBY: qva->qva_source |= RPMQV_TRIGGEREDBY; break; ++ case POPT_QUERYBYPATH: qva->qva_source |= RPMQV_PATH_ALL; break; + case POPT_QUERYBYPKGID: qva->qva_source |= RPMQV_PKGID; break; + case POPT_QUERYBYHDRID: qva->qva_source |= RPMQV_HDRID; break; + case POPT_QUERYBYTID: qva->qva_source |= RPMQV_TID; break; +@@ -80,7 +82,9 @@ struct poptOption rpmQVSourcePoptTable[] = { + { "checksig", 'K', POPT_ARGFLAG_DOC_HIDDEN, NULL, 'K', + N_("rpm checksig mode"), NULL }, + { "file", 'f', 0, 0, 'f', +- N_("query/verify package(s) owning file"), "FILE" }, ++ N_("query/verify package(s) owning installed file"), "FILE" }, ++ { "path", '\0', 0, 0, POPT_QUERYBYPATH, ++ N_("query/verify package(s) owning path, installed or not"), "PATH" }, + { "group", 'g', 0, 0, 'g', + N_("query/verify package(s) in group"), "GROUP" }, + { "package", 'p', 0, 0, 'p', +diff --git a/lib/query.c b/lib/query.c +index fdabe6e52..9a71f0dc5 100644 +--- a/lib/query.c ++++ b/lib/query.c +@@ -445,6 +445,7 @@ static rpmdbMatchIterator initQueryIterator(QVA_t qva, rpmts ts, const char * ar + } + /* fallthrough on absolute and relative paths */ + case RPMQV_PATH: ++ case RPMQV_PATH_ALL: + { char * fn; + + for (s = arg; *s != '\0'; s++) +@@ -463,8 +464,10 @@ static rpmdbMatchIterator initQueryIterator(QVA_t qva, rpmts ts, const char * ar + fn = xstrdup(arg); + (void) rpmCleanPath(fn); + +- /* XXX Add a switch to enable former BASENAMES behavior? */ +- mi = rpmtsInitIterator(ts, RPMDBI_INSTFILENAMES, fn, 0); ++ rpmDbiTagVal tag = RPMDBI_INSTFILENAMES; ++ if (qva->qva_source == RPMQV_PATH_ALL) ++ tag = RPMDBI_BASENAMES; ++ mi = rpmtsInitIterator(ts, tag, fn, 0); + if (mi == NULL) + mi = rpmtsInitIterator(ts, RPMDBI_PROVIDENAME, fn, 0); + +diff --git a/lib/rpmcli.h b/lib/rpmcli.h +index 4886c2453..3961418e7 100644 +--- a/lib/rpmcli.h ++++ b/lib/rpmcli.h +@@ -101,6 +101,7 @@ enum rpmQVSources_e { + RPMQV_SPECBUILTRPMS, /*!< ... from pkgs which would be built from spec */ + RPMQV_WHATOBSOLETES, /*!< ... from obsoletes db search. */ + RPMQV_WHATCONFLICTS, /*!< ... from conflicts db search. */ ++ RPMQV_PATH_ALL, /*!< ... from file path db search (all states). */ + }; + + typedef rpmFlags rpmQVSources; +diff --git a/tests/rpmquery.at b/tests/rpmquery.at +index 9a4f1cb76..335d5ee0d 100644 +--- a/tests/rpmquery.at ++++ b/tests/rpmquery.at +@@ -201,6 +201,58 @@ runroot rpm \ + + AT_CLEANUP + ++# ------------------------------ ++# query a package by a file ++AT_SETUP([rpm -qf]) ++AT_KEYWORDS([query]) ++AT_CHECK([ ++RPMDB_INIT ++runroot rpm \ ++ --nodeps \ ++ -i /data/RPMS/hello-1.0-1.i386.rpm ++runroot rpm \ ++ -qf /usr/local/bin/hello ++], ++[0], ++[hello-1.0-1.i386 ++], ++[]) ++AT_CLEANUP ++ ++AT_SETUP([rpm -qf on non-installed file]) ++AT_KEYWORDS([query]) ++AT_CHECK([ ++RPMDB_INIT ++runroot rpm \ ++ --nodeps \ ++ --excludedocs \ ++ -i /data/RPMS/hello-1.0-1.i386.rpm ++runroot rpm \ ++ -qf /usr/share/doc/hello-1.0/FAQ ++], ++[1], ++[], ++[error: file /usr/share/doc/hello-1.0/FAQ: No such file or directory ++]) ++AT_CLEANUP ++ ++AT_SETUP([rpm -q --path on non-installed file]) ++AT_KEYWORDS([query]) ++AT_CHECK([ ++RPMDB_INIT ++runroot rpm \ ++ --nodeps \ ++ --excludedocs \ ++ -i /data/RPMS/hello-1.0-1.i386.rpm ++runroot rpm \ ++ -q --path /usr/share/doc/hello-1.0/FAQ ++], ++[0], ++[hello-1.0-1.i386 ++], ++[]) ++AT_CLEANUP ++ + # ------------------------------ + AT_SETUP([integer array query]) + AT_KEYWORDS([query]) +-- +2.35.1 + diff --git a/SOURCES/rpm-4.16.1.3-bump-rpmdb-cookie-hash-to-SHA256-for-FIPS.patch b/SOURCES/rpm-4.16.1.3-bump-rpmdb-cookie-hash-to-SHA256-for-FIPS.patch new file mode 100644 index 0000000..998e1f8 --- /dev/null +++ b/SOURCES/rpm-4.16.1.3-bump-rpmdb-cookie-hash-to-SHA256-for-FIPS.patch @@ -0,0 +1,32 @@ +From a26f6655546158153807017e7ded2aff5e4e10e4 Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Mon, 31 Jan 2022 11:13:35 +0200 +Subject: [PATCH] Bump hash for rpmdb cookie to SHA256 to appease FIPS + +The rpmdb cookie is not a security feature, but as these existing +hashes are more convenient than coming up with our own... we then +run into the great big wall of FIPS which in its current incarnation +disallows use of SHA1. And so rpmdbCookie() fails under current FIPS. + +Just bumping the algorithm to SHA256 seems the path of lowest +resistance, whether that algo makes sense for this purpose or not. +--- + lib/rpmdb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/rpmdb.c b/lib/rpmdb.c +index 01d49a641..00bd4236f 100644 +--- a/lib/rpmdb.c ++++ b/lib/rpmdb.c +@@ -2642,7 +2642,7 @@ char *rpmdbCookie(rpmdb db) + rpmdbIndexIterator ii = rpmdbIndexIteratorInit(db, RPMDBI_NAME); + + if (ii) { +- DIGEST_CTX ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE); ++ DIGEST_CTX ctx = rpmDigestInit(PGPHASHALGO_SHA256, RPMDIGEST_NONE); + const void *key = 0; + size_t keylen = 0; + while ((rpmdbIndexIteratorNext(ii, &key, &keylen)) == 0) { +-- +2.34.1 + diff --git a/SOURCES/rpm-4.16.1.3-fix-IMA-sig-len-assumed-const.patch b/SOURCES/rpm-4.16.1.3-fix-IMA-sig-len-assumed-const.patch new file mode 100644 index 0000000..8c29342 --- /dev/null +++ b/SOURCES/rpm-4.16.1.3-fix-IMA-sig-len-assumed-const.patch @@ -0,0 +1,288 @@ +From b66422161d68ed7f7b1cb30e4db900bf42bed146 Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Mon, 29 Nov 2021 14:01:39 +0200 +Subject: [PATCH 1/4] Add Python bindings for rpmfilesFSignature() + +Only, use more descriptive names than the C-side counterparts. +Python has nice facilities for dealing with binary data so return it +as such rather than converting to hex. + +Backported for 4.16.1.3 (removed rpmfilesVSignature()). +--- + python/rpmfiles-py.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/python/rpmfiles-py.c b/python/rpmfiles-py.c +index 27666021d..48189a0ac 100644 +--- a/python/rpmfiles-py.c ++++ b/python/rpmfiles-py.c +@@ -152,6 +152,22 @@ static PyObject *rpmfile_digest(rpmfileObject *s) + Py_RETURN_NONE; + } + ++static PyObject *bytebuf(const unsigned char *buf, size_t len) ++{ ++ if (buf) { ++ PyObject *o = PyBytes_FromStringAndSize((const char *)buf, len); ++ return o; ++ } ++ Py_RETURN_NONE; ++} ++ ++static PyObject *rpmfile_imasig(rpmfileObject *s) ++{ ++ size_t len = 0; ++ const unsigned char *sig = rpmfilesFSignature(s->files, s->ix, &len); ++ return bytebuf(sig, len); ++} ++ + static PyObject *rpmfile_class(rpmfileObject *s) + { + return utf8FromString(rpmfilesFClass(s->files, s->ix)); +@@ -278,6 +294,8 @@ static PyGetSetDef rpmfile_getseters[] = { + "language the file provides (typically for doc files)" }, + { "caps", (getter) rpmfile_caps, NULL, + "file capabilities" }, ++ { "imasig", (getter) rpmfile_imasig, NULL, ++ "IMA signature" }, + { NULL, NULL, NULL, NULL } + }; + +-- +2.35.1 + +From 9c4622998d3d0666edbea3ed1ae518502c3ed987 Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Mon, 7 Feb 2022 11:52:55 +0200 +Subject: [PATCH 2/4] Add a testcase for --dump query + +--- + tests/rpmquery.at | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/tests/rpmquery.at b/tests/rpmquery.at +index 9a4f1cb76..9bd391ac5 100644 +--- a/tests/rpmquery.at ++++ b/tests/rpmquery.at +@@ -83,6 +83,24 @@ hello.spec + [ignore]) + AT_CLEANUP + ++AT_SETUP([rpm -qp --dump]) ++AT_KEYWORDS([query]) ++AT_CHECK([ ++RPMDB_INIT ++runroot rpm \ ++ -qp --dump \ ++ /data/RPMS/hello-2.0-1.x86_64.rpm ++], ++[0], ++[/usr/bin/hello 7120 1489670606 c89fa87aeb1143969c0b6be9334b21d932f77f74e8f60120b5de316406369cf0 0100751 root root 0 0 0 X ++/usr/share/doc/hello-2.0 4096 1489670606 0000000000000000000000000000000000000000000000000000000000000000 040755 root root 0 0 0 X ++/usr/share/doc/hello-2.0/COPYING 48 908894882 fac3b28492ecdc16da172a6f1a432ceed356ca4d9248157b2a962b395e37b3b0 0100644 root root 0 1 0 X ++/usr/share/doc/hello-2.0/FAQ 36 908895030 678b87e217a415f05e43460e2c7b668245b412e2b4f18a75aa7399d9774ed0b4 0100644 root root 0 1 0 X ++/usr/share/doc/hello-2.0/README 39 908884468 d63fdc6c986106f57230f217d36b2395d83ecf491d2b7187af714dc8db9629e9 0100644 root root 0 1 0 X ++], ++[]) ++AT_CLEANUP ++ + # ------------------------------ + AT_SETUP([rpmspec -q]) + AT_KEYWORDS([query]) +-- +2.35.1 + +From 9b2bc10881db7691439005fd74ea53d75b15ac76 Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Thu, 10 Feb 2022 11:15:04 +0200 +Subject: [PATCH 3/4] Ensure sane string lengths for file digests from header + +--- + lib/rpmfi.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/lib/rpmfi.c b/lib/rpmfi.c +index af428468c..2dffab3aa 100644 +--- a/lib/rpmfi.c ++++ b/lib/rpmfi.c +@@ -1501,6 +1501,10 @@ static uint8_t *hex2bin(Header h, rpmTagVal tag, rpm_count_t num, size_t len) + t += len; + continue; + } ++ if (strlen(s) != len * 2) { ++ bin = rfree(bin); ++ break; ++ } + for (int j = 0; j < len; j++, t++, s += 2) + *t = (rnibble(s[0]) << 4) | rnibble(s[1]); + } +-- +2.35.1 + +From ddfed9e1842a1b60a8c40de3a18add6f6d68c515 Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Mon, 29 Nov 2021 14:01:39 +0200 +Subject: [PATCH 4/4] Fix IMA signature fubar, take III (#1833, RhBug:2018937) + +At least ECDSA and RSA signatures can vary in length, but the IMA code +assumes constant lengths and thus may either place invalid signatures on +disk from either truncating or overshooting, and segfault if the stars are +just so. + +As we can't assume static lengths and attempts to use maximum length +have proven problematic for other reasons, use a data structure that +can actually handle variable length data properly: store offsets into +the decoded binary blob and use them to calculate lengths when needed, +empty data is simply consequtive identical offsets. This avoids a whole +class of silly overflow issues with multiplying, makes zero-length data +actually presentable in the data structure and saves memory too. + +Add tests to show behavior with variable length signatures and missing +signatures. + +Additionally update the signing code to store the largest IMA signature +length rather than what happened to be last to be on the safe side. +We can't rely on this value due to invalid packages being out there, +but then we need to calculate the lengths on rpmfiles populate so there's +not a lot to gain anyhow. + +Fixes: #1833 + +Backported for 4.16.1.3. Note that the test case has been removed due +to it including a binary file (test package) for which we'd have to use +-Sgit with %autopatch and thus depend on git-core at build time. +Nevertheless, we do have this BZ covered in our internal test suite, so +no need for it anyway. +--- + lib/rpmfi.c | 61 +++++++++++++++++++++++++++++++++++++++------ + sign/rpmsignfiles.c | 5 +++- + 2 files changed, 58 insertions(+), 8 deletions(-) + +diff --git a/lib/rpmfi.c b/lib/rpmfi.c +index 2dffab3aa..77e73442c 100644 +--- a/lib/rpmfi.c ++++ b/lib/rpmfi.c +@@ -115,7 +115,7 @@ struct rpmfiles_s { + struct fingerPrint_s * fps; /*!< File fingerprint(s). */ + + int digestalgo; /*!< File digest algorithm */ +- int signaturelength; /*!< File signature length */ ++ uint32_t *signatureoffs; /*!< File signature offsets */ + unsigned char * digests; /*!< File digests in binary. */ + unsigned char * signatures; /*!< File signatures in binary. */ + +@@ -574,10 +574,15 @@ const unsigned char * rpmfilesFSignature(rpmfiles fi, int ix, size_t *len) + const unsigned char *signature = NULL; + + if (fi != NULL && ix >= 0 && ix < rpmfilesFC(fi)) { +- if (fi->signatures != NULL) +- signature = fi->signatures + (fi->signaturelength * ix); ++ size_t slen = 0; ++ if (fi->signatures != NULL && fi->signatureoffs != NULL) { ++ uint32_t off = fi->signatureoffs[ix]; ++ slen = fi->signatureoffs[ix+1] - off; ++ if (slen > 0) ++ signature = fi->signatures + off; ++ } + if (len) +- *len = fi->signaturelength; ++ *len = slen; + } + return signature; + } +@@ -1257,6 +1262,7 @@ rpmfiles rpmfilesFree(rpmfiles fi) + fi->flangs = _free(fi->flangs); + fi->digests = _free(fi->digests); + fi->signatures = _free(fi->signatures); ++ fi->signatureoffs = _free(fi->signatureoffs); + fi->fcaps = _free(fi->fcaps); + + fi->cdict = _free(fi->cdict); +@@ -1485,6 +1491,48 @@ err: + return; + } + ++/* ++ * Convert a tag of variable len hex strings to binary presentation, ++ * accessed via offsets to a contiguous binary blob. Empty values ++ * are represented by identical consequtive offsets. The offsets array ++ * always has one extra element to allow calculating the size of the ++ * last element. ++ */ ++static uint8_t *hex2binv(Header h, rpmTagVal tag, rpm_count_t num, ++ uint32_t **offsetp) ++{ ++ struct rpmtd_s td; ++ uint8_t *bin = NULL; ++ uint32_t *offs = NULL; ++ ++ if (headerGet(h, tag, &td, HEADERGET_MINMEM) && rpmtdCount(&td) == num) { ++ const char *s; ++ int i = 0; ++ uint8_t *t = bin = xmalloc(((rpmtdSize(&td) / 2) + 1)); ++ offs = xmalloc((num + 1) * sizeof(*offs)); ++ ++ while ((s = rpmtdNextString(&td))) { ++ uint32_t slen = strlen(s); ++ uint32_t len = slen / 2; ++ if (slen % 2) { ++ bin = rfree(bin); ++ offs = rfree(offs); ++ goto exit; ++ } ++ offs[i] = t - bin; ++ for (int j = 0; j < len; j++, t++, s += 2) ++ *t = (rnibble(s[0]) << 4) | rnibble(s[1]); ++ i++; ++ } ++ offs[i] = t - bin; ++ *offsetp = offs; ++ } ++ ++exit: ++ rpmtdFreeData(&td); ++ return bin; ++} ++ + /* Convert a tag of hex strings to binary presentation */ + static uint8_t *hex2bin(Header h, rpmTagVal tag, rpm_count_t num, size_t len) + { +@@ -1580,9 +1628,8 @@ static int rpmfilesPopulate(rpmfiles fi, Header h, rpmfiFlags flags) + fi->signatures = NULL; + /* grab hex signatures from header and store in binary format */ + if (!(flags & RPMFI_NOFILESIGNATURES)) { +- fi->signaturelength = headerGetNumber(h, RPMTAG_FILESIGNATURELENGTH); +- fi->signatures = hex2bin(h, RPMTAG_FILESIGNATURES, +- totalfc, fi->signaturelength); ++ fi->signatures = hex2binv(h, RPMTAG_FILESIGNATURES, ++ totalfc, &fi->signatureoffs); + } + + /* XXX TR_REMOVED doesn;t need fmtimes, frdevs, finodes */ +diff --git a/sign/rpmsignfiles.c b/sign/rpmsignfiles.c +index b143c5b9b..372ba634c 100644 +--- a/sign/rpmsignfiles.c ++++ b/sign/rpmsignfiles.c +@@ -98,8 +98,9 @@ rpmRC rpmSignFiles(Header sigh, Header h, const char *key, char *keypass) + td.count = 1; + + while (rpmfiNext(fi) >= 0) { ++ uint32_t slen = 0; + digest = rpmfiFDigest(fi, NULL, NULL); +- signature = signFile(algoname, digest, diglen, key, keypass, &siglen); ++ signature = signFile(algoname, digest, diglen, key, keypass, &slen); + if (!signature) { + rpmlog(RPMLOG_ERR, _("signFile failed\n")); + goto exit; +@@ -110,6 +111,8 @@ rpmRC rpmSignFiles(Header sigh, Header h, const char *key, char *keypass) + goto exit; + } + signature = _free(signature); ++ if (slen > siglen) ++ siglen = slen; + } + + if (siglen > 0) { +-- +2.35.1 + diff --git a/SOURCES/rpm-4.16.1.3-fix-regression-reading-rpm-v3-pkgs.patch b/SOURCES/rpm-4.16.1.3-fix-regression-reading-rpm-v3-pkgs.patch new file mode 100644 index 0000000..1e8a922 --- /dev/null +++ b/SOURCES/rpm-4.16.1.3-fix-regression-reading-rpm-v3-pkgs.patch @@ -0,0 +1,88 @@ +From f5695d04f56e27d9cf947c0502eb549c28aa817e Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Tue, 25 May 2021 14:07:18 +0300 +Subject: [PATCH] Fix regression reading rpm v3 and other rare packages (#1635) + +Commit d6a86b5e69e46cc283b1e06c92343319beb42e21 introduced far stricter +checks on what tags are allowed in signature and main headers than rpm +had previously seen, and unsurprisingly this introduced some regressions +on less common cases: + +- On rpm v3 packages and some newer 3rd party created packages (such as + install4j < 9.0.2), RPMTAG_ARCHIVESIZE resides in the main header + to begin with +- In rpm 4.13 - 4.14, file IMA signatures were incorrectly placed in + the main header. + +As a quirk, permit the existence of RPMTAG_ARCHIVESIZE, +RPMTAG_FILESIGNATURES and RPMTAG_FILESIGNATURELENGTH in the main header +too provided that the corresponding signature tag is not there (so +they can reside in either but not both headers). + +Initial workaround patch by Demi Marie Obenour. + +Fixes: #1635 + +Backported for 4.16.1.3. +--- + lib/package.c | 35 ++++++++++++++++++++--------------- + 1 file changed, 20 insertions(+), 15 deletions(-) + +diff --git a/lib/package.c b/lib/package.c +index 36ed5abc6..8c2b66b0b 100644 +--- a/lib/package.c ++++ b/lib/package.c +@@ -35,21 +35,22 @@ struct taglate_s { + rpmTagVal stag; + rpmTagVal xtag; + rpm_count_t count; ++ int quirk; + } const xlateTags[] = { +- { RPMSIGTAG_SIZE, RPMTAG_SIGSIZE, 1 }, +- { RPMSIGTAG_PGP, RPMTAG_SIGPGP, 0 }, +- { RPMSIGTAG_MD5, RPMTAG_SIGMD5, 16 }, +- { RPMSIGTAG_GPG, RPMTAG_SIGGPG, 0 }, +- /* { RPMSIGTAG_PGP5, RPMTAG_SIGPGP5, 0 }, */ /* long obsolete, dont use */ +- { RPMSIGTAG_PAYLOADSIZE, RPMTAG_ARCHIVESIZE, 1 }, +- { RPMSIGTAG_FILESIGNATURES, RPMTAG_FILESIGNATURES, 0 }, +- { RPMSIGTAG_FILESIGNATURELENGTH, RPMTAG_FILESIGNATURELENGTH, 1 }, +- { RPMSIGTAG_SHA1, RPMTAG_SHA1HEADER, 1 }, +- { RPMSIGTAG_SHA256, RPMTAG_SHA256HEADER, 1 }, +- { RPMSIGTAG_DSA, RPMTAG_DSAHEADER, 0 }, +- { RPMSIGTAG_RSA, RPMTAG_RSAHEADER, 0 }, +- { RPMSIGTAG_LONGSIZE, RPMTAG_LONGSIGSIZE, 1 }, +- { RPMSIGTAG_LONGARCHIVESIZE, RPMTAG_LONGARCHIVESIZE, 1 }, ++ { RPMSIGTAG_SIZE, RPMTAG_SIGSIZE, 1, 0 }, ++ { RPMSIGTAG_PGP, RPMTAG_SIGPGP, 0, 0 }, ++ { RPMSIGTAG_MD5, RPMTAG_SIGMD5, 16, 0 }, ++ { RPMSIGTAG_GPG, RPMTAG_SIGGPG, 0, 0 }, ++ /* { RPMSIGTAG_PGP5, RPMTAG_SIGPGP5, 0, 0 }, */ /* long obsolete, dont use */ ++ { RPMSIGTAG_PAYLOADSIZE, RPMTAG_ARCHIVESIZE, 1, 1 }, ++ { RPMSIGTAG_FILESIGNATURES, RPMTAG_FILESIGNATURES, 0, 1 }, ++ { RPMSIGTAG_FILESIGNATURELENGTH, RPMTAG_FILESIGNATURELENGTH, 1, 1 }, ++ { RPMSIGTAG_SHA1, RPMTAG_SHA1HEADER, 1, 0 }, ++ { RPMSIGTAG_SHA256, RPMTAG_SHA256HEADER, 1, 0 }, ++ { RPMSIGTAG_DSA, RPMTAG_DSAHEADER, 0, 0 }, ++ { RPMSIGTAG_RSA, RPMTAG_RSAHEADER, 0, 0 }, ++ { RPMSIGTAG_LONGSIZE, RPMTAG_LONGSIGSIZE, 1, 0 }, ++ { RPMSIGTAG_LONGARCHIVESIZE, RPMTAG_LONGARCHIVESIZE, 1, 0 }, + { 0 } + }; + +@@ -67,8 +68,12 @@ rpmTagVal headerMergeLegacySigs(Header h, Header sigh, char **msg) + + for (xl = xlateTags; xl->stag; xl++) { + /* There mustn't be one in the main header */ +- if (headerIsEntry(h, xl->xtag)) ++ if (headerIsEntry(h, xl->xtag)) { ++ /* Some tags may exist in either header, but never both */ ++ if (xl->quirk && !headerIsEntry(sigh, xl->stag)) ++ continue; + goto exit; ++ } + } + + rpmtdReset(&td); +-- +2.35.1 + diff --git a/SOURCES/rpm-4.16.1.3-fix-spurious-transfiletriggerpostun-execution.patch b/SOURCES/rpm-4.16.1.3-fix-spurious-transfiletriggerpostun-execution.patch new file mode 100644 index 0000000..7142d40 --- /dev/null +++ b/SOURCES/rpm-4.16.1.3-fix-spurious-transfiletriggerpostun-execution.patch @@ -0,0 +1,123 @@ +From 8c37dff4ce9c887eda5ad61f78001e87473002ed Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Tue, 16 Nov 2021 11:49:18 +0200 +Subject: [PATCH] Fix spurious %transfiletriggerpostun execution + (RhBug:2023311) + +If a package has multiple %transfiletriggerpostun triggers, any one +of them matching would cause all of them to run, due to disconnect +in the intel gathering stage: we'd gather all the headers with matching +files into a lump, and then add any postun triggers found in them, +but this loses the triggering file information and causes all postuns +to run. + +The triggers need to be added while looping over the file matches, +like runFileTriggers() does. Doing so actually simplifies the code. +These should really be unified to use the same code, but leaving +that exercise to another rainy day. + +Combined with 0988ccb53abf426587d228df5c60c4042da71999 (fix-up). +--- + lib/rpmtriggers.c | 65 ++++++++++++++++++++++++----------------------- + 1 file changed, 33 insertions(+), 32 deletions(-) + +diff --git a/lib/rpmtriggers.c b/lib/rpmtriggers.c +index fc809a65e..8d8f57450 100644 +--- a/lib/rpmtriggers.c ++++ b/lib/rpmtriggers.c +@@ -97,19 +97,39 @@ static void rpmtriggersSortAndUniq(rpmtriggers trigs) + } + } + ++static void addTriggers(rpmts ts, Header trigH, rpmsenseFlags filter, ++ const char *prefix) ++{ ++ int tix = 0; ++ rpmds ds; ++ rpmds triggers = rpmdsNew(trigH, RPMTAG_TRANSFILETRIGGERNAME, 0); ++ ++ while ((ds = rpmdsFilterTi(triggers, tix))) { ++ if ((rpmdsNext(ds) >= 0) && (rpmdsFlags(ds) & filter) && ++ strcmp(prefix, rpmdsN(ds)) == 0) { ++ struct rpmtd_s priorities; ++ ++ if (headerGet(trigH, RPMTAG_TRANSFILETRIGGERPRIORITIES, ++ &priorities, HEADERGET_MINMEM)) { ++ rpmtdSetIndex(&priorities, tix); ++ rpmtriggersAdd(ts->trigs2run, headerGetInstance(trigH), ++ tix, *rpmtdGetUint32(&priorities)); ++ } ++ } ++ rpmdsFree(ds); ++ tix++; ++ } ++ rpmdsFree(triggers); ++} ++ + void rpmtriggersPrepPostUnTransFileTrigs(rpmts ts, rpmte te) + { +- rpmdbMatchIterator mi; + rpmdbIndexIterator ii; +- Header trigH; + const void *key; + size_t keylen; + rpmfiles files; +- rpmds rpmdsTriggers; +- rpmds rpmdsTrigger; + + ii = rpmdbIndexIteratorInit(rpmtsGetRdb(ts), RPMDBI_TRANSFILETRIGGERNAME); +- mi = rpmdbNewIterator(rpmtsGetRdb(ts), RPMDBI_PACKAGES); + files = rpmteFiles(te); + + /* Iterate over file triggers in rpmdb */ +@@ -121,39 +141,20 @@ void rpmtriggersPrepPostUnTransFileTrigs(rpmts ts, rpmte te) + rpmfi fi = rpmfilesFindPrefix(files, pfx); + while (rpmfiNext(fi) >= 0) { + if (RPMFILE_IS_INSTALLED(rpmfiFState(fi))) { +- /* If yes then store it */ +- rpmdbAppendIterator(mi, rpmdbIndexIteratorPkgOffsets(ii), +- rpmdbIndexIteratorNumPkgs(ii)); ++ unsigned int npkg = rpmdbIndexIteratorNumPkgs(ii); ++ const unsigned int *offs = rpmdbIndexIteratorPkgOffsets(ii); ++ /* Save any postun triggers matching this prefix */ ++ for (int i = 0; i < npkg; i++) { ++ Header h = rpmdbGetHeaderAt(rpmtsGetRdb(ts), offs[i]); ++ addTriggers(ts, h, RPMSENSE_TRIGGERPOSTUN, pfx); ++ headerFree(h); ++ } + break; + } + } + rpmfiFree(fi); + } + rpmdbIndexIteratorFree(ii); +- +- if (rpmdbGetIteratorCount(mi)) { +- /* Filter triggers and save only trans postun triggers into ts */ +- while ((trigH = rpmdbNextIterator(mi)) != NULL) { +- int tix = 0; +- rpmdsTriggers = rpmdsNew(trigH, RPMTAG_TRANSFILETRIGGERNAME, 0); +- while ((rpmdsTrigger = rpmdsFilterTi(rpmdsTriggers, tix))) { +- if ((rpmdsNext(rpmdsTrigger) >= 0) && +- (rpmdsFlags(rpmdsTrigger) & RPMSENSE_TRIGGERPOSTUN)) { +- struct rpmtd_s priorities; +- +- headerGet(trigH, RPMTAG_TRANSFILETRIGGERPRIORITIES, +- &priorities, HEADERGET_MINMEM); +- rpmtdSetIndex(&priorities, tix); +- rpmtriggersAdd(ts->trigs2run, rpmdbGetIteratorOffset(mi), +- tix, *rpmtdGetUint32(&priorities)); +- } +- rpmdsFree(rpmdsTrigger); +- tix++; +- } +- rpmdsFree(rpmdsTriggers); +- } +- } +- rpmdbFreeIterator(mi); + rpmfilesFree(files); + } + +-- +2.35.1 + diff --git a/SOURCES/rpm-4.16.1.3-hashtab-use-after-free-fix.patch b/SOURCES/rpm-4.16.1.3-hashtab-use-after-free-fix.patch new file mode 100644 index 0000000..eee3cc3 --- /dev/null +++ b/SOURCES/rpm-4.16.1.3-hashtab-use-after-free-fix.patch @@ -0,0 +1,13 @@ +diff -up rpm-4.16.1.3/tools/hashtab.c.orig rpm-4.16.1.3/tools/hashtab.c +--- rpm-4.16.1.3/tools/hashtab.c.orig 2021-07-01 14:51:24.576237269 +0200 ++++ rpm-4.16.1.3/tools/hashtab.c 2021-07-01 15:02:42.005754968 +0200 +@@ -292,7 +292,8 @@ htab_expand (htab) + } + while (p < olimit); + +- free (oentries); ++ if (oentries != htab->entries) ++ free(oentries); + return 1; + } + diff --git a/SOURCES/rpm-4.16.1.3-imp-covscan-fixes.patch b/SOURCES/rpm-4.16.1.3-imp-covscan-fixes.patch new file mode 100644 index 0000000..02d77cc --- /dev/null +++ b/SOURCES/rpm-4.16.1.3-imp-covscan-fixes.patch @@ -0,0 +1,286 @@ +commit c7d7c5acd0c14d0450016887cba1d86483086794 +Author: Michal Domonkos +Date: Mon Jun 21 10:05:10 2021 +0200 + + Add quoting to literal curly brackets + + These curly brackets are already treated as literals by the shell, so + let's make that explicit for clarity, and silence a ShellCheck warning + at the same time. + + More info: https://github.com/koalaman/shellcheck/wiki/SC1083 + + Found by ShellCheck. + + Adjusted for 4.16.1.3 + +diff -up rpm-4.16.1.3/scripts/check-rpaths-worker.orig rpm-4.16.1.3/scripts/check-rpaths-worker +--- rpm-4.16.1.3/scripts/check-rpaths-worker.orig 2021-06-29 15:34:31.671003589 +0200 ++++ rpm-4.16.1.3/scripts/check-rpaths-worker 2021-06-29 15:34:51.993414093 +0200 +@@ -120,13 +120,13 @@ for i; do + (/lib64/*|/usr/lib64/*|/usr/X11R6/lib64/*|/usr/local/lib64/*) + badness=0;; + +- (\$ORIGIN|\${ORIGINX}|\$ORIGIN/*|\${ORIGINX}/*) ++ (\$ORIGIN|\$\{ORIGINX\}|\$ORIGIN/*|\$\{ORIGINX\}/*) + test $allow_ORIGIN -eq 0 && badness=8 || { + badness=0 + new_allow_ORIGIN=1 + } + ;; +- (/*\$PLATFORM*|/*\${PLATFORM}*|/*\$LIB*|/*\${LIB}*) ++ (/*\$PLATFORM*|/*\$\{PLATFORM\}*|/*\$LIB*|/*\$\{LIB\}*) + badness=0;; + + (/lib|/usr/lib|/usr/X11R6/lib) +From d8dc4fd37b1d90cd97de7fcf484d449ec132c9b3 Mon Sep 17 00:00:00 2001 +From: Michal Domonkos +Date: Wed, 9 Jun 2021 21:31:40 +0200 +Subject: [PATCH 1/7] Fix memory leak in sqlexec() + +Callers are supposed to free the error strings themselves: +https://www.sqlite.org/capi3ref.html#sqlite3_exec + +Found by Coverity. +--- + lib/backend/sqlite.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/lib/backend/sqlite.c b/lib/backend/sqlite.c +index 7c2de45aa..dbefeb163 100644 +--- a/lib/backend/sqlite.c ++++ b/lib/backend/sqlite.c +@@ -233,6 +233,7 @@ static int sqlexec(sqlite3 *sdb, const char *fmt, ...) + rpmlog(RPMLOG_DEBUG, "%s: %d\n", cmd, rc); + + sqlite3_free(cmd); ++ sqlite3_free(err); + + return rc ? RPMRC_FAIL : RPMRC_OK; + } +-- +2.31.1 + +From 5baf73feb4951cc3b3f553a4b18d3b3599cbf87c Mon Sep 17 00:00:00 2001 +From: Michal Domonkos +Date: Fri, 25 Jun 2021 11:21:46 +0200 +Subject: [PATCH 2/7] Always free the arg list passed to rpmGlob() + +Even though the actual implementation of rpmGlob() does not allocate the +passed arg list (av) if the return code (rc) is non-zero or arg count +(ac) is 0, it's the responsibility of the caller (rpmInstall() here) to +free that memory, so make sure we do that irrespectively of the above +conditions. + +Found by Coverity. +--- + lib/rpminstall.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/lib/rpminstall.c b/lib/rpminstall.c +index 724126e94..302ec0ba1 100644 +--- a/lib/rpminstall.c ++++ b/lib/rpminstall.c +@@ -461,6 +461,7 @@ int rpmInstall(rpmts ts, struct rpmInstallArguments_s * ia, ARGV_t fileArgv) + rpmlog(RPMLOG_ERR, _("File not found by glob: %s\n"), *eiu->fnp); + } + eiu->numFailed++; ++ argvFree(av); + continue; + } + +-- +2.31.1 + +From 3c8b01b67ec907afaaffe71691fa41b878578527 Mon Sep 17 00:00:00 2001 +From: Michal Domonkos +Date: Mon, 14 Jun 2021 10:21:25 +0200 +Subject: [PATCH 3/7] Fix resource leak in Fts_children() + +This function is not used anywhere within our codebase (and neither is +it part of the public API) so it's basically a no-op... Still, rather +than yanking it completely, let's just silence the Coverity error here. + +Found by Coverity. +--- + misc/fts.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/misc/fts.c b/misc/fts.c +index d3ebb2946..caf27495d 100644 +--- a/misc/fts.c ++++ b/misc/fts.c +@@ -585,8 +585,10 @@ Fts_children(FTS * sp, int instr) + if ((fd = __open(".", O_RDONLY, 0)) < 0) + return (NULL); + sp->fts_child = fts_build(sp, instr); +- if (__fchdir(fd)) ++ if (__fchdir(fd)) { ++ (void)__close(fd); + return (NULL); ++ } + (void)__close(fd); + return (sp->fts_child); + } +-- +2.31.1 + +From 39b7bf8579e0522cf16347b3a7e332d3b6d742c6 Mon Sep 17 00:00:00 2001 +From: Michal Domonkos +Date: Mon, 14 Jun 2021 12:34:23 +0200 +Subject: [PATCH 4/7] Fix memory leak in fts_build() + +Turns out this leak is already fixed in glibc's current version of fts.c +(where our copy originates from), so let's just backport that. + +Original commit in glibc: +https://sourceware.org/git/?p=glibc.git;\ +a=commit;h=db67c2c98b89a5723af44df54f38b779de8d4a65 + +Found by Coverity. +--- + misc/fts.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/misc/fts.c b/misc/fts.c +index caf27495d..f7fce0eaa 100644 +--- a/misc/fts.c ++++ b/misc/fts.c +@@ -855,6 +855,7 @@ mem1: saved_errno = errno; + fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) { + cur->fts_info = FTS_ERR; + SET(FTS_STOP); ++ fts_lfree(head); + return (NULL); + } + +@@ -862,6 +863,7 @@ mem1: saved_errno = errno; + if (!nitems) { + if (type == BREAD) + cur->fts_info = FTS_DP; ++ fts_lfree(head); + return (NULL); + } + +-- +2.31.1 + +From 9c093c4f092dd6bd1e0c8d2b852a72b74db076c2 Mon Sep 17 00:00:00 2001 +From: Michal Domonkos +Date: Tue, 15 Jun 2021 13:34:21 +0200 +Subject: [PATCH 5/7] Fix memory leak in decodePkts() + +Found by Coverity. +--- + rpmio/rpmpgp.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c +index c59185dce..ee5c81e24 100644 +--- a/rpmio/rpmpgp.c ++++ b/rpmio/rpmpgp.c +@@ -1371,9 +1371,13 @@ static pgpArmor decodePkts(uint8_t *b, uint8_t **pkt, size_t *pktlen) + crc = pgpCRC(dec, declen); + if (crcpkt != crc) { + ec = PGPARMOR_ERR_CRC_CHECK; ++ _free(dec); + goto exit; + } +- if (pkt) *pkt = dec; ++ if (pkt) ++ *pkt = dec; ++ else ++ _free(dec); + if (pktlen) *pktlen = declen; + ec = PGPARMOR_PUBKEY; /* XXX ASCII Pubkeys only, please. */ + goto exit; +-- +2.31.1 + +From 590b2fc06252567eb7d57197dc361a8b459d62a3 Mon Sep 17 00:00:00 2001 +From: Michal Domonkos +Date: Mon, 21 Jun 2021 17:51:14 +0200 +Subject: [PATCH 6/7] Fix memory leak with multiple %lang-s in one line + +We permit two equivalent forms of specifying a list of languages per +file: + + %lang(xx,yy,zz) /path/to/file + %lang(xx) %lang(yy) %lang(zz) /path/to/file + +The leak was when parsing the second form. + +Found by Coverity. +--- + build/files.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/build/files.c b/build/files.c +index f8153ad2b..0c8859f6c 100644 +--- a/build/files.c ++++ b/build/files.c +@@ -777,6 +777,8 @@ static rpmRC parseForLang(char * buf, FileEntry cur) + + if (*pe == ',') pe++; /* skip , if present */ + } ++ ++ q = _free(q); + } + + rc = RPMRC_OK; +-- +2.31.1 + +From b7a1e996326ee29a163d67ceb1e6127fdc251c14 Mon Sep 17 00:00:00 2001 +From: Michal Domonkos +Date: Fri, 25 Jun 2021 15:15:08 +0200 +Subject: [PATCH 7/7] Fix memory leaks in Lua rex extension + +This covers the following usage: + +expr = rex.newPOSIX() +expr:match() # A leak occurred here +expr:gmatch(, ) # A leak occurred here + +Found by Coverity. +--- + luaext/lrexlib.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/luaext/lrexlib.c b/luaext/lrexlib.c +index 09c5a6454..0f29b6371 100644 +--- a/luaext/lrexlib.c ++++ b/luaext/lrexlib.c +@@ -80,6 +80,7 @@ static void rex_push_matches(lua_State *L, const char *text, regmatch_t *match, + + static int rex_match(lua_State *L) + { ++ int rc = 0; + int res; + #ifdef REG_BASIC + size_t len; +@@ -109,9 +110,10 @@ static int rex_match(lua_State *L) + lua_pushstring(L, "n"); + lua_pushnumber(L, ncapt); + lua_rawset(L, -3); +- return 3; +- } else +- return 0; ++ rc = 3; ++ } ++ free(match); ++ return rc; + } + + static int rex_gmatch(lua_State *L) +@@ -158,6 +160,7 @@ static int rex_gmatch(lua_State *L) + break; + } + lua_pushnumber(L, nmatch); ++ free(match); + return 1; + } + +-- +2.31.1 + diff --git a/SOURCES/rpm-4.16.1.3-rpmsign-support-EdDSA-sig.patch b/SOURCES/rpm-4.16.1.3-rpmsign-support-EdDSA-sig.patch new file mode 100644 index 0000000..12507fe --- /dev/null +++ b/SOURCES/rpm-4.16.1.3-rpmsign-support-EdDSA-sig.patch @@ -0,0 +1,20 @@ +commit 23770e1a4f28c56a31fe600cae332c77333b60b6 +Author: Demi Marie Obenour +Date: Sat Mar 6 03:23:41 2021 -0500 + + rpmsign: support EdDSA signatures + + They were previously rejected + +diff --git a/sign/rpmgensig.c b/sign/rpmgensig.c +index 28cd91576..d8c84e937 100644 +--- a/sign/rpmgensig.c ++++ b/sign/rpmgensig.c +@@ -155,6 +155,7 @@ static rpmtd makeSigTag(Header sigh, int ishdr, uint8_t *pkt, size_t pktlen) + pubkey_algo = pgpDigParamsAlgo(sigp, PGPVAL_PUBKEYALGO); + switch (pubkey_algo) { + case PGPPUBKEYALGO_DSA: ++ case PGPPUBKEYALGO_EDDSA: + sigtag = ishdr ? RPMSIGTAG_DSA : RPMSIGTAG_GPG; + break; + case PGPPUBKEYALGO_RSA: diff --git a/SOURCES/rpm-4.16.1.3-skip-recorded-symlinks-in-setperms.patch b/SOURCES/rpm-4.16.1.3-skip-recorded-symlinks-in-setperms.patch new file mode 100644 index 0000000..6e3acf8 --- /dev/null +++ b/SOURCES/rpm-4.16.1.3-skip-recorded-symlinks-in-setperms.patch @@ -0,0 +1,40 @@ +From 6cdcdd8770d1f0b9ba706dcc1e6392a59dbe3fe5 Mon Sep 17 00:00:00 2001 +From: Michal Domonkos +Date: Tue, 7 Dec 2021 08:08:37 +0100 +Subject: [PATCH] Skip recorded symlinks in --setperms (RhBug:1900662) + +If a package contains a symlink in the buildroot which is declared as a +ghost or config file but is a regular file or directory on the system +where it's installed, a --setperms call will reset its permissions to +those of a symlink (777 on Linux), which almost certainly is not the +correct thing to do. + +To fix that, just skip files that were recorded as symlinks. + +This is a special case of a general issue in --setperms; since file +permission semantics may change depending on the file type, to stay on +the safe side, any (ghost or config) file whose type changes after +installation should probably be skipped. However, symlinks are the most +prominent case here, so let's just focus on that now and avoid adding +too much cleverness to a popt alias (this got us into trouble not too +long ago, see commits 38c2f6e and 0d83637). We may revisit this in the +eventual C implementation. +--- + rpmpopt.in | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/rpmpopt.in b/rpmpopt.in +index 27d298651..d5a6b140b 100644 +--- a/rpmpopt.in ++++ b/rpmpopt.in +@@ -44,6 +44,7 @@ rpm alias --scripts --qf '\ + --POPTdesc=$"list install/erase scriptlets from package(s)" + + rpm alias --setperms -q --qf '[\[ -L %{FILENAMES:shescape} \] || \ ++ \[ -n %{FILELINKTOS:shescape} \] || \ + ( \[ $((%{FILEFLAGS} & 2#1001000)) != 0 \] && \[ ! -e %{FILENAMES:shescape} \] ) || \ + chmod %7{FILEMODES:octal} %{FILENAMES:shescape}\n]' \ + --pipe "grep -v \(none\) | grep '^. -L ' | sed 's/chmod .../chmod /' | sh" \ +-- +2.34.1 + diff --git a/SOURCES/rpm-4.16.1.3-support-bdb-hash-v8.patch b/SOURCES/rpm-4.16.1.3-support-bdb-hash-v8.patch new file mode 100644 index 0000000..3581544 --- /dev/null +++ b/SOURCES/rpm-4.16.1.3-support-bdb-hash-v8.patch @@ -0,0 +1,39 @@ +From c771ae28e28b2971869b7801ffc7961f4dcb6544 Mon Sep 17 00:00:00 2001 +From: Panu Matilainen +Date: Thu, 10 Jun 2021 10:32:12 +0300 +Subject: [PATCH] Support hash v8 databases from BDB < 4.6 in bdb_ro + +In Hash v8 databases page type differs from newer ones to denote +the difference between sorted and unsorted pages. + +Fixes reading rpm databases from older distros like SLES 11 and RHEL 5 +(RhBug:1965147) +--- + lib/backend/bdb_ro.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/lib/backend/bdb_ro.c b/lib/backend/bdb_ro.c +index 2667ec845..695ef78e3 100644 +--- a/lib/backend/bdb_ro.c ++++ b/lib/backend/bdb_ro.c +@@ -276,7 +276,7 @@ static int hash_lookup(struct bdb_cur *cur, const unsigned char *key, unsigned i + pg = hash_bucket_to_page(cur->db, bucket); + if (bdb_getpage(cur->db, cur->page, pg)) + return -1; +- if (cur->page[25] != 8 && cur->page[25] != 13) ++ if (cur->page[25] != 8 && cur->page[25] != 13 && cur->page[25] != 2) + return -1; + cur->idx = (unsigned int)-2; + cur->numidx = *(uint16_t *)(cur->page + 20); +@@ -323,7 +323,7 @@ static int hash_next(struct bdb_cur *cur) + } + if (bdb_getpage(cur->db, cur->page, pg)) + return -1; +- if (cur->page[25] != 8 && cur->page[25] != 13) ++ if (cur->page[25] != 8 && cur->page[25] != 13 && cur->page[25] != 2) + return -1; + cur->numidx = *(uint16_t *)(cur->page + 20); + continue; +-- +2.33.1 + diff --git a/SOURCES/rpm-4.16.1.3-unblock-signals-in-forked-scriptlets.patch b/SOURCES/rpm-4.16.1.3-unblock-signals-in-forked-scriptlets.patch new file mode 100644 index 0000000..55713ed --- /dev/null +++ b/SOURCES/rpm-4.16.1.3-unblock-signals-in-forked-scriptlets.patch @@ -0,0 +1,32 @@ +commit cb6aa82dbc10d554f8d234e934ae7c77e39a3ce2 +Author: Panu Matilainen +Date: Tue Jan 12 13:35:23 2021 +0200 + + Unblock signals in forked scriptlets + + Since commit c5f82d3f6223ebd0c5cc0a07ea60393ae7284929 we've blocked + most signals during transactions, which makes sense to rpm itself but + the signal mask is inherited to childs and carried even across exec(), + so all scriptlets are executing with those signals blocked as well. + Which in turn does not make sense, the scriptlets could run stuff that + actually depends on signal delivery (such as SIGALARM in RhBug:1913765). + + Unblock all signals for forked scriptlet execution (Lua scriptlets are + totally different as they execute in-process for now) + +diff --git a/lib/rpmscript.c b/lib/rpmscript.c +index 2ae3378f7..c69d29554 100644 +--- a/lib/rpmscript.c ++++ b/lib/rpmscript.c +@@ -152,6 +152,11 @@ static void doScriptExec(ARGV_const_t argv, ARGV_const_t prefixes, + FD_t scriptFd, FD_t out) + { + int xx; ++ sigset_t set; ++ ++ /* Unmask all signals, the scripts may need them */ ++ sigfillset(&set); ++ sigprocmask(SIG_UNBLOCK, &set, NULL); + + /* SIGPIPE is ignored in rpm, reset to default for the scriptlet */ + (void) signal(SIGPIPE, SIG_DFL); diff --git a/SOURCES/rpm-4.16.1.3-unbreak-checking-of-installed-rich-deps.patch b/SOURCES/rpm-4.16.1.3-unbreak-checking-of-installed-rich-deps.patch new file mode 100644 index 0000000..43184bc --- /dev/null +++ b/SOURCES/rpm-4.16.1.3-unbreak-checking-of-installed-rich-deps.patch @@ -0,0 +1,144 @@ +From 137ecc2e1841c2b27b99d4db9006253dd1c73dde Mon Sep 17 00:00:00 2001 +From: Michael Schroeder +Date: Fri, 4 Jun 2021 23:30:49 +0200 +Subject: [PATCH] Unbreak checking of installed rich dependencies + +Commit ddb32b9187e9ce85819a84ca8d202131fd9f8b9f added an +extra check that tests if the provide we are checking really +intersects the dependency from rpmdb. Unfortunately the +rpmdsCompare() call does not understand rich dependencies and +will consider them as not intersecting. + +Unbreak the check by not doing the intersection test for +rich dependencies. We'll improve this in a later commit. + +Also add test cases for dependency problems with installed +rich dependencies. +--- + lib/depends.c | 2 +- + tests/rpmdeps.at | 99 ++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 100 insertions(+), 1 deletion(-) + +diff --git a/lib/depends.c b/lib/depends.c +index c10ba4bda..fecbd9675 100644 +--- a/lib/depends.c ++++ b/lib/depends.c +@@ -846,7 +846,7 @@ static void checkInstDeps(rpmts ts, depCache dcache, rpmte te, + rpmdsSetIx(ds, rpmdbGetIteratorFileNum(mi)); + + /* Is it in our range at all? (but file deps have no range) */ +- if (depds) ++ if (depds && !rpmdsIsRich(ds)) + match = rpmdsCompare(ds, depds); + + if (match && unsatisfiedDepend(ts, dcache, ds) == is_problem) { +diff --git a/tests/rpmdeps.at b/tests/rpmdeps.at +index 67bde1dc8..8357af9df 100644 +--- a/tests/rpmdeps.at ++++ b/tests/rpmdeps.at +@@ -732,3 +732,102 @@ runroot rpm -U /build/RPMS/noarch/deptest-one-1.0-1.noarch.rpm /build/RPMS/noarc + [], + []) + AT_CLEANUP ++ ++# ------------------------------ ++# ++AT_SETUP([install to break installed rich dependency]) ++AT_KEYWORDS([install, boolean]) ++RPMDB_INIT ++ ++runroot rpmbuild --quiet -bb \ ++ --define "pkg one" \ ++ --define "cfls (deptest-three or deptest-five)" \ ++ /data/SPECS/deptest.spec ++runroot rpmbuild --quiet -bb \ ++ --define "pkg two" \ ++ --define "reqs (deptest-five if deptest-four)" \ ++ /data/SPECS/deptest.spec ++runroot rpmbuild --quiet -bb \ ++ --define "pkg three" \ ++ /data/SPECS/deptest.spec ++runroot rpmbuild --quiet -bb \ ++ --define "pkg four" \ ++ /data/SPECS/deptest.spec ++ ++# installed conflict with "or" clause ++AT_CHECK([ ++RPMDB_INIT ++ ++runroot rpm -U /build/RPMS/noarch/deptest-one-1.0-1.noarch.rpm ++runroot rpm -U /build/RPMS/noarch/deptest-three-1.0-1.noarch.rpm ++], ++[1], ++[], ++[error: Failed dependencies: ++ (deptest-three or deptest-five) conflicts with (installed) deptest-one-1.0-1.noarch ++]) ++ ++# installed requires with "if" clause ++AT_CHECK([ ++RPMDB_INIT ++ ++runroot rpm -U /build/RPMS/noarch/deptest-two-1.0-1.noarch.rpm ++runroot rpm -U /build/RPMS/noarch/deptest-four-1.0-1.noarch.rpm ++], ++[1], ++[], ++[error: Failed dependencies: ++ (deptest-five if deptest-four) is needed by (installed) deptest-two-1.0-1.noarch ++]) ++AT_CLEANUP ++ ++# ------------------------------ ++# ++AT_SETUP([erase to break installed rich dependency]) ++AT_KEYWORDS([install, boolean]) ++RPMDB_INIT ++ ++runroot rpmbuild --quiet -bb \ ++ --define "pkg one" \ ++ --define "reqs (deptest-three or deptest-five)" \ ++ /data/SPECS/deptest.spec ++runroot rpmbuild --quiet -bb \ ++ --define "pkg two" \ ++ --define "cfls (deptest-five unless deptest-four)" \ ++ /data/SPECS/deptest.spec ++runroot rpmbuild --quiet -bb \ ++ --define "pkg three" \ ++ /data/SPECS/deptest.spec ++runroot rpmbuild --quiet -bb \ ++ --define "pkg four" \ ++ /data/SPECS/deptest.spec ++runroot rpmbuild --quiet -bb \ ++ --define "pkg five" \ ++ /data/SPECS/deptest.spec ++ ++# installed requires with "or" clause ++AT_CHECK([ ++RPMDB_INIT ++ ++runroot rpm -U /build/RPMS/noarch/deptest-one-1.0-1.noarch.rpm /build/RPMS/noarch/deptest-three-1.0-1.noarch.rpm ++runroot rpm -e deptest-three ++], ++[1], ++[], ++[error: Failed dependencies: ++ (deptest-three or deptest-five) is needed by (installed) deptest-one-1.0-1.noarch ++]) ++ ++# installed conflicts with "unless" clause ++AT_CHECK([ ++RPMDB_INIT ++ ++runroot rpm -U /build/RPMS/noarch/deptest-two-1.0-1.noarch.rpm /build/RPMS/noarch/deptest-four-1.0-1.noarch.rpm /build/RPMS/noarch/deptest-five-1.0-1.noarch.rpm ++runroot rpm -e deptest-four ++], ++[1], ++[], ++[error: Failed dependencies: ++ (deptest-five unless deptest-four) conflicts with (installed) deptest-two-1.0-1.noarch ++]) ++AT_CLEANUP +-- +2.33.1 + diff --git a/SOURCES/rpm-4.16.1.3-validate-and-require-subkey-binding-sigs.patch b/SOURCES/rpm-4.16.1.3-validate-and-require-subkey-binding-sigs.patch new file mode 100644 index 0000000..878f6e4 --- /dev/null +++ b/SOURCES/rpm-4.16.1.3-validate-and-require-subkey-binding-sigs.patch @@ -0,0 +1,401 @@ +From 32b21da4bae5b8fbe0f42c31b723c4963b4b2512 Mon Sep 17 00:00:00 2001 +From: Demi Marie Obenour +Date: Thu, 6 May 2021 18:34:45 -0400 +Subject: [PATCH] Validate and require subkey binding signatures on PGP public + keys + +All subkeys must be followed by a binding signature by the primary key +as per the OpenPGP RFC, enforce the presence and validity in the parser. + +The implementation is as kludgey as they come to work around our +simple-minded parser structure without touching API, to maximise +backportability. Store all the raw packets internally as we decode them +to be able to access previous elements at will, needed to validate ordering +and access the actual data. Add testcases for manipulated keys whose +import previously would succeed. + +Combined with: +5ff86764b17f31535cb247543a90dd739076ec38 +b5e8bc74b2b05aa557f663fe227b94d2bc64fbd8 +9f03f42e2614a68f589f9db8fe76287146522c0c +b6dffb6dc5ffa2ddc389743f0507876cab341315 (mem-leak fix) +ae3d2d234ae47ff85229d3fce97a266fa1aa5a61 (use-after-free fix) + +Fixes CVE-2021-3521. +--- + rpmio/rpmpgp.c | 122 +++++++++++++++--- + sign/rpmgensig.c | 2 +- + tests/Makefile.am | 3 + + tests/data/keys/CVE-2021-3521-badbind.asc | 25 ++++ + .../data/keys/CVE-2021-3521-nosubsig-last.asc | 25 ++++ + tests/data/keys/CVE-2021-3521-nosubsig.asc | 37 ++++++ + tests/rpmsigdig.at | 28 ++++ + 7 files changed, 224 insertions(+), 18 deletions(-) + create mode 100644 tests/data/keys/CVE-2021-3521-badbind.asc + create mode 100644 tests/data/keys/CVE-2021-3521-nosubsig-last.asc + create mode 100644 tests/data/keys/CVE-2021-3521-nosubsig.asc + +diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c +index d0688ebe9..3372d577d 100644 +--- a/rpmio/rpmpgp.c ++++ b/rpmio/rpmpgp.c +@@ -515,7 +515,7 @@ pgpDigAlg pgpDigAlgFree(pgpDigAlg alg) + return NULL; + } + +-static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, uint8_t sigtype, ++static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, + const uint8_t *p, const uint8_t *h, size_t hlen, + pgpDigParams sigp) + { +@@ -528,10 +528,8 @@ static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, uint8_t sigtype, + int mpil = pgpMpiLen(p); + if (p + mpil > pend) + break; +- if (sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT) { +- if (sigalg->setmpi(sigalg, i, p)) +- break; +- } ++ if (sigalg->setmpi(sigalg, i, p)) ++ break; + p += mpil; + } + +@@ -604,7 +602,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen, + } + + p = ((uint8_t *)v) + sizeof(*v); +- rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p, h, hlen, _digp); ++ rc = pgpPrtSigParams(tag, v->pubkey_algo, p, h, hlen, _digp); + } break; + case 4: + { pgpPktSigV4 v = (pgpPktSigV4)h; +@@ -662,7 +660,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen, + if (p > (h + hlen)) + return 1; + +- rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p, h, hlen, _digp); ++ rc = pgpPrtSigParams(tag, v->pubkey_algo, p, h, hlen, _digp); + } break; + default: + rpmlog(RPMLOG_WARNING, _("Unsupported version of key: V%d\n"), version); +@@ -1041,36 +1039,127 @@ unsigned int pgpDigParamsAlgo(pgpDigParams digp, unsigned int algotype) + return algo; + } + ++static pgpDigParams pgpDigParamsNew(uint8_t tag) ++{ ++ pgpDigParams digp = xcalloc(1, sizeof(*digp)); ++ digp->tag = tag; ++ return digp; ++} ++ ++static int hashKey(DIGEST_CTX hash, const struct pgpPkt *pkt, int exptag) ++{ ++ int rc = -1; ++ if (pkt->tag == exptag) { ++ uint8_t head[] = { ++ 0x99, ++ (pkt->blen >> 8), ++ (pkt->blen ), ++ }; ++ ++ rpmDigestUpdate(hash, head, 3); ++ rpmDigestUpdate(hash, pkt->body, pkt->blen); ++ rc = 0; ++ } ++ return rc; ++} ++ ++static int pgpVerifySelf(pgpDigParams key, pgpDigParams selfsig, ++ const struct pgpPkt *all, int i) ++{ ++ int rc = -1; ++ DIGEST_CTX hash = NULL; ++ ++ switch (selfsig->sigtype) { ++ case PGPSIGTYPE_SUBKEY_BINDING: ++ hash = rpmDigestInit(selfsig->hash_algo, 0); ++ if (hash) { ++ rc = hashKey(hash, &all[0], PGPTAG_PUBLIC_KEY); ++ if (!rc) ++ rc = hashKey(hash, &all[i-1], PGPTAG_PUBLIC_SUBKEY); ++ } ++ break; ++ default: ++ /* ignore types we can't handle */ ++ rc = 0; ++ break; ++ } ++ ++ if (hash && rc == 0) ++ rc = pgpVerifySignature(key, selfsig, hash); ++ ++ rpmDigestFinal(hash, NULL, NULL, 0); ++ ++ return rc; ++} ++ + int pgpPrtParams(const uint8_t * pkts, size_t pktlen, unsigned int pkttype, + pgpDigParams * ret) + { + const uint8_t *p = pkts; + const uint8_t *pend = pkts + pktlen; + pgpDigParams digp = NULL; +- struct pgpPkt pkt; ++ pgpDigParams selfsig = NULL; ++ int i = 0; ++ int alloced = 16; /* plenty for normal cases */ ++ struct pgpPkt *all = xmalloc(alloced * sizeof(*all)); + int rc = -1; /* assume failure */ ++ int expect = 0; ++ int prevtag = 0; + + while (p < pend) { +- if (decodePkt(p, (pend - p), &pkt)) ++ struct pgpPkt *pkt = &all[i]; ++ if (decodePkt(p, (pend - p), pkt)) + break; + + if (digp == NULL) { +- if (pkttype && pkt.tag != pkttype) { ++ if (pkttype && pkt->tag != pkttype) { + break; + } else { +- digp = xcalloc(1, sizeof(*digp)); +- digp->tag = pkt.tag; ++ digp = pgpDigParamsNew(pkt->tag); + } + } + +- if (pgpPrtPkt(&pkt, digp)) ++ if (expect) { ++ if (pkt->tag != expect) ++ break; ++ selfsig = pgpDigParamsNew(pkt->tag); ++ } ++ ++ if (pgpPrtPkt(pkt, selfsig ? selfsig : digp)) + break; + +- p += (pkt.body - pkt.head) + pkt.blen; ++ if (selfsig) { ++ /* subkeys must be followed by binding signature */ ++ int xx = 1; /* assume failure */ ++ ++ if (!(prevtag == PGPTAG_PUBLIC_SUBKEY && ++ selfsig->sigtype != PGPSIGTYPE_SUBKEY_BINDING)) ++ xx = pgpVerifySelf(digp, selfsig, all, i); ++ ++ selfsig = pgpDigParamsFree(selfsig); ++ if (xx) ++ break; ++ expect = 0; ++ } ++ ++ if (pkt->tag == PGPTAG_PUBLIC_SUBKEY) ++ expect = PGPTAG_SIGNATURE; ++ prevtag = pkt->tag; ++ ++ i++; ++ p += (pkt->body - pkt->head) + pkt->blen; ++ if (pkttype == PGPTAG_SIGNATURE) ++ break; ++ ++ if (alloced <= i) { ++ alloced *= 2; ++ all = xrealloc(all, alloced * sizeof(*all)); ++ } + } + +- rc = (digp && (p == pend)) ? 0 : -1; ++ rc = (digp && (p == pend) && expect == 0) ? 0 : -1; + ++ free(all); + if (ret && rc == 0) { + *ret = digp; + } else { +@@ -1105,8 +1194,7 @@ int pgpPrtParamsSubkeys(const uint8_t *pkts, size_t pktlen, + digps = xrealloc(digps, alloced * sizeof(*digps)); + } + +- digps[count] = xcalloc(1, sizeof(**digps)); +- digps[count]->tag = PGPTAG_PUBLIC_SUBKEY; ++ digps[count] = pgpDigParamsNew(PGPTAG_PUBLIC_SUBKEY); + /* Copy UID from main key to subkey */ + digps[count]->userid = xstrdup(mainkey->userid); + +diff --git a/sign/rpmgensig.c b/sign/rpmgensig.c +index e5d191cc0..988a0f611 100644 +--- a/sign/rpmgensig.c ++++ b/sign/rpmgensig.c +@@ -351,7 +351,7 @@ static int haveSignature(rpmtd sigtd, Header h) + pgpPrtParams(oldtd.data, oldtd.count, PGPTAG_SIGNATURE, &sig2); + if (pgpDigParamsCmp(sig1, sig2) == 0) + rc = 1; +- pgpDigParamsFree(sig2); ++ sig2 = pgpDigParamsFree(sig2); + } + pgpDigParamsFree(sig1); + rpmtdFreeData(&oldtd); +diff --git a/tests/Makefile.am b/tests/Makefile.am +index f742a9e1d..328234278 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -107,6 +107,9 @@ EXTRA_DIST += data/SPECS/hello-config-buildid.spec + EXTRA_DIST += data/SPECS/hello-cd.spec + EXTRA_DIST += data/keys/rpm.org-rsa-2048-test.pub + EXTRA_DIST += data/keys/rpm.org-rsa-2048-test.secret ++EXTRA_DIST += data/keys/CVE-2021-3521-badbind.asc ++EXTRA_DIST += data/keys/CVE-2021-3521-nosubsig.asc ++EXTRA_DIST += data/keys/CVE-2021-3521-nosubsig-last.asc + EXTRA_DIST += data/macros.testfile + EXTRA_DIST += data/macros.debug + EXTRA_DIST += data/SOURCES/foo.c +diff --git a/tests/data/keys/CVE-2021-3521-badbind.asc b/tests/data/keys/CVE-2021-3521-badbind.asc +new file mode 100644 +index 000000000..aea00f9d7 +--- /dev/null ++++ b/tests/data/keys/CVE-2021-3521-badbind.asc +@@ -0,0 +1,25 @@ ++-----BEGIN PGP PUBLIC KEY BLOCK----- ++Version: rpm-4.17.90 (NSS-3) ++ ++mQENBFjmORgBCAC7TMEk6wnjSs8Dr4yqSScWdU2pjcqrkTxuzdWvowcIUPZI0w/g ++HkRqGd4apjvY2V15kjL10gk3QhFP3pZ/9p7zh8o8NHX7aGdSGDK7NOq1eFaErPRY ++91LW9RiZ0lbOjXEzIL0KHxUiTQEmdXJT43DJMFPyW9fkCWg0OltiX618FUdWWfI8 ++eySdLur1utnqBvdEbCUvWK2RX3vQZQdvEBODnNk2pxqTyV0w6VPQ96W++lF/5Aas ++7rUv3HIyIXxIggc8FRrnH+y9XvvHDonhTIlGnYZN4ubm9i4y3gOkrZlGTrEw7elQ ++1QeMyG2QQEbze8YjpTm4iLABCBrRfPRaQpwrABEBAAG0IXJwbS5vcmcgUlNBIHRl ++c3RrZXkgPHJzYUBycG0ub3JnPokBNwQTAQgAIQUCWOY5GAIbAwULCQgHAgYVCAkK ++CwIEFgIDAQIeAQIXgAAKCRBDRFkeGWTF/MxxCACnjqFL+MmPh9W9JQKT2DcLbBzf ++Cqo6wcEBoCOcwgRSk8dSikhARoteoa55JRJhuMyeKhhEAogE9HRmCPFdjezFTwgB ++BDVBpO2dZ023mLXDVCYX3S8pShOgCP6Tn4wqCnYeAdLcGg106N4xcmgtcssJE+Pr ++XzTZksbZsrTVEmL/Ym+R5w5jBfFnGk7Yw7ndwfQsfNXQb5AZynClFxnX546lcyZX ++fEx3/e6ezw57WNOUK6WT+8b+EGovPkbetK/rGxNXuWaP6X4A/QUm8O98nCuHYFQq +++mvNdsCBqGf7mhaRGtpHk/JgCn5rFvArMDqLVrR9hX0LdCSsH7EGE+bR3r7wuQEN ++BFjmORgBCACk+vDZrIXQuFXEYToZVwb2attzbbJJCqD71vmZTLsW0QxuPKRgbcYY ++zp4K4lVBnHhFrF8MOUOxJ7kQWIJZMZFt+BDcptCYurbD2H4W2xvnWViiC+LzCMzz ++iMJT6165uefL4JHTDPxC2fFiM9yrc72LmylJNkM/vepT128J5Qv0gRUaQbHiQuS6 ++Dm/+WRnUfx3i89SV4mnBxb/Ta93GVqoOciWwzWSnwEnWYAvOb95JL4U7c5J5f/+c ++KnQDHsW7sIiIdscsWzvgf6qs2Ra1Zrt7Fdk4+ZS2f/adagLhDO1C24sXf5XfMk5m ++L0OGwZSr9m5s17VXxfspgU5ugc8kBJfzABEBAAE= ++=WCfs ++-----END PGP PUBLIC KEY BLOCK----- ++ +diff --git a/tests/data/keys/CVE-2021-3521-nosubsig-last.asc b/tests/data/keys/CVE-2021-3521-nosubsig-last.asc +new file mode 100644 +index 000000000..aea00f9d7 +--- /dev/null ++++ b/tests/data/keys/CVE-2021-3521-nosubsig-last.asc +@@ -0,0 +1,25 @@ ++-----BEGIN PGP PUBLIC KEY BLOCK----- ++Version: rpm-4.17.90 (NSS-3) ++ ++mQENBFjmORgBCAC7TMEk6wnjSs8Dr4yqSScWdU2pjcqrkTxuzdWvowcIUPZI0w/g ++HkRqGd4apjvY2V15kjL10gk3QhFP3pZ/9p7zh8o8NHX7aGdSGDK7NOq1eFaErPRY ++91LW9RiZ0lbOjXEzIL0KHxUiTQEmdXJT43DJMFPyW9fkCWg0OltiX618FUdWWfI8 ++eySdLur1utnqBvdEbCUvWK2RX3vQZQdvEBODnNk2pxqTyV0w6VPQ96W++lF/5Aas ++7rUv3HIyIXxIggc8FRrnH+y9XvvHDonhTIlGnYZN4ubm9i4y3gOkrZlGTrEw7elQ ++1QeMyG2QQEbze8YjpTm4iLABCBrRfPRaQpwrABEBAAG0IXJwbS5vcmcgUlNBIHRl ++c3RrZXkgPHJzYUBycG0ub3JnPokBNwQTAQgAIQUCWOY5GAIbAwULCQgHAgYVCAkK ++CwIEFgIDAQIeAQIXgAAKCRBDRFkeGWTF/MxxCACnjqFL+MmPh9W9JQKT2DcLbBzf ++Cqo6wcEBoCOcwgRSk8dSikhARoteoa55JRJhuMyeKhhEAogE9HRmCPFdjezFTwgB ++BDVBpO2dZ023mLXDVCYX3S8pShOgCP6Tn4wqCnYeAdLcGg106N4xcmgtcssJE+Pr ++XzTZksbZsrTVEmL/Ym+R5w5jBfFnGk7Yw7ndwfQsfNXQb5AZynClFxnX546lcyZX ++fEx3/e6ezw57WNOUK6WT+8b+EGovPkbetK/rGxNXuWaP6X4A/QUm8O98nCuHYFQq +++mvNdsCBqGf7mhaRGtpHk/JgCn5rFvArMDqLVrR9hX0LdCSsH7EGE+bR3r7wuQEN ++BFjmORgBCACk+vDZrIXQuFXEYToZVwb2attzbbJJCqD71vmZTLsW0QxuPKRgbcYY ++zp4K4lVBnHhFrF8MOUOxJ7kQWIJZMZFt+BDcptCYurbD2H4W2xvnWViiC+LzCMzz ++iMJT6165uefL4JHTDPxC2fFiM9yrc72LmylJNkM/vepT128J5Qv0gRUaQbHiQuS6 ++Dm/+WRnUfx3i89SV4mnBxb/Ta93GVqoOciWwzWSnwEnWYAvOb95JL4U7c5J5f/+c ++KnQDHsW7sIiIdscsWzvgf6qs2Ra1Zrt7Fdk4+ZS2f/adagLhDO1C24sXf5XfMk5m ++L0OGwZSr9m5s17VXxfspgU5ugc8kBJfzABEBAAE= ++=WCfs ++-----END PGP PUBLIC KEY BLOCK----- ++ +diff --git a/tests/data/keys/CVE-2021-3521-nosubsig.asc b/tests/data/keys/CVE-2021-3521-nosubsig.asc +new file mode 100644 +index 000000000..3a2e7417f +--- /dev/null ++++ b/tests/data/keys/CVE-2021-3521-nosubsig.asc +@@ -0,0 +1,37 @@ ++-----BEGIN PGP PUBLIC KEY BLOCK----- ++Version: rpm-4.17.90 (NSS-3) ++ ++mQENBFjmORgBCAC7TMEk6wnjSs8Dr4yqSScWdU2pjcqrkTxuzdWvowcIUPZI0w/g ++HkRqGd4apjvY2V15kjL10gk3QhFP3pZ/9p7zh8o8NHX7aGdSGDK7NOq1eFaErPRY ++91LW9RiZ0lbOjXEzIL0KHxUiTQEmdXJT43DJMFPyW9fkCWg0OltiX618FUdWWfI8 ++eySdLur1utnqBvdEbCUvWK2RX3vQZQdvEBODnNk2pxqTyV0w6VPQ96W++lF/5Aas ++7rUv3HIyIXxIggc8FRrnH+y9XvvHDonhTIlGnYZN4ubm9i4y3gOkrZlGTrEw7elQ ++1QeMyG2QQEbze8YjpTm4iLABCBrRfPRaQpwrABEBAAG0IXJwbS5vcmcgUlNBIHRl ++c3RrZXkgPHJzYUBycG0ub3JnPokBNwQTAQgAIQUCWOY5GAIbAwULCQgHAgYVCAkK ++CwIEFgIDAQIeAQIXgAAKCRBDRFkeGWTF/MxxCACnjqFL+MmPh9W9JQKT2DcLbBzf ++Cqo6wcEBoCOcwgRSk8dSikhARoteoa55JRJhuMyeKhhEAogE9HRmCPFdjezFTwgB ++BDVBpO2dZ023mLXDVCYX3S8pShOgCP6Tn4wqCnYeAdLcGg106N4xcmgtcssJE+Pr ++XzTZksbZsrTVEmL/Ym+R5w5jBfFnGk7Yw7ndwfQsfNXQb5AZynClFxnX546lcyZX ++fEx3/e6ezw57WNOUK6WT+8b+EGovPkbetK/rGxNXuWaP6X4A/QUm8O98nCuHYFQq +++mvNdsCBqGf7mhaRGtpHk/JgCn5rFvArMDqLVrR9hX0LdCSsH7EGE+bR3r7wuQEN ++BFjmORgBCACk+vDZrIXQuFXEYToZVwb2attzbbJJCqD71vmZTLsW0QxuPKRgbcYY ++zp4K4lVBnHhFrF8MOUOxJ7kQWIJZMZFt+BDcptCYurbD2H4W2xvnWViiC+LzCMzz ++iMJT6165uefL4JHTDPxC2fFiM9yrc72LmylJNkM/vepT128J5Qv0gRUaQbHiQuS6 ++Dm/+WRnUfx3i89SV4mnBxb/Ta93GVqoOciWwzWSnwEnWYAvOb95JL4U7c5J5f/+c ++KnQDHsW7sIiIdscsWzvgf6qs2Ra1Zrt7Fdk4+ZS2f/adagLhDO1C24sXf5XfMk5m ++L0OGwZSr9m5s17VXxfspgU5ugc8kBJfzABEBAAG5AQ0EWOY5GAEIAKT68NmshdC4 ++VcRhOhlXBvZq23NtskkKoPvW+ZlMuxbRDG48pGBtxhjOngriVUGceEWsXww5Q7En ++uRBYglkxkW34ENym0Ji6tsPYfhbbG+dZWKIL4vMIzPOIwlPrXrm558vgkdMM/ELZ ++8WIz3KtzvYubKUk2Qz+96lPXbwnlC/SBFRpBseJC5LoOb/5ZGdR/HeLz1JXiacHF ++v9Nr3cZWqg5yJbDNZKfASdZgC85v3kkvhTtzknl//5wqdAMexbuwiIh2xyxbO+B/ ++qqzZFrVmu3sV2Tj5lLZ/9p1qAuEM7ULbixd/ld8yTmYvQ4bBlKv2bmzXtVfF+ymB ++Tm6BzyQEl/MAEQEAAYkBHwQYAQgACQUCWOY5GAIbDAAKCRBDRFkeGWTF/PANB/9j ++mifmj6z/EPe0PJFhrpISt9PjiUQCt0IPtiL5zKAkWjHePIzyi+0kCTBF6DDLFxos ++3vN4bWnVKT1kBhZAQlPqpJTg+m74JUYeDGCdNx9SK7oRllATqyu+5rncgxjWVPnQ ++zu/HRPlWJwcVFYEVXYL8xzfantwQTqefjmcRmBRdA2XJITK+hGWwAmrqAWx+q5xX ++Pa8wkNMxVzNS2rUKO9SoVuJ/wlUvfoShkJ/VJ5HDp3qzUqncADfdGN35TDzscngQ ++gHvnMwVBfYfSCABV1hNByoZcc/kxkrWMmsd/EnIyLd1Q1baKqc3cEDuC6E6/o4yJ ++E4XX4jtDmdZPreZALsiB ++=rRop ++-----END PGP PUBLIC KEY BLOCK----- ++ +diff --git a/tests/rpmsigdig.at b/tests/rpmsigdig.at +index e1a3ab062..705fc5870 100644 +--- a/tests/rpmsigdig.at ++++ b/tests/rpmsigdig.at +@@ -240,6 +240,34 @@ gpg(185e6146f00650f8) = 4:185e6146f00650f8-58e63918 + []) + AT_CLEANUP + ++AT_SETUP([rpmkeys --import invalid keys]) ++AT_KEYWORDS([rpmkeys import]) ++RPMDB_INIT ++ ++AT_CHECK([ ++runroot rpmkeys --import /data/keys/CVE-2021-3521-badbind.asc ++], ++[1], ++[], ++[error: /data/keys/CVE-2021-3521-badbind.asc: key 1 import failed.] ++) ++AT_CHECK([ ++runroot rpmkeys --import /data/keys/CVE-2021-3521-nosubsig.asc ++], ++[1], ++[], ++[error: /data/keys/CVE-2021-3521-nosubsig.asc: key 1 import failed.] ++) ++ ++AT_CHECK([ ++runroot rpmkeys --import /data/keys/CVE-2021-3521-nosubsig-last.asc ++], ++[1], ++[], ++[error: /data/keys/CVE-2021-3521-nosubsig-last.asc: key 1 import failed.] ++) ++AT_CLEANUP ++ + # ------------------------------ + # Test pre-built package verification + AT_SETUP([rpmkeys -K 1]) +-- +2.34.1 + diff --git a/SOURCES/rpm-4.7.1-geode-i686.patch b/SOURCES/rpm-4.7.1-geode-i686.patch new file mode 100644 index 0000000..2e8692a --- /dev/null +++ b/SOURCES/rpm-4.7.1-geode-i686.patch @@ -0,0 +1,14 @@ +diff --git a/rpmrc.in b/rpmrc.in +index 4a6cca9..d62ddaf 100644 +--- a/rpmrc.in ++++ b/rpmrc.in +@@ -281,7 +281,7 @@ arch_compat: alphaev5: alpha + arch_compat: alpha: axp noarch + + arch_compat: athlon: i686 +-arch_compat: geode: i586 ++arch_compat: geode: i686 + arch_compat: pentium4: pentium3 + arch_compat: pentium3: i686 + arch_compat: i686: i586 + diff --git a/SOURCES/rpm-4.9.90-no-man-dirs.patch b/SOURCES/rpm-4.9.90-no-man-dirs.patch new file mode 100644 index 0000000..04f276a --- /dev/null +++ b/SOURCES/rpm-4.9.90-no-man-dirs.patch @@ -0,0 +1,12 @@ +diff -up rpm-4.9.90.git11486/scripts/find-lang.sh.no-man-dirs rpm-4.9.90.git11486/scripts/find-lang.sh +--- rpm-4.9.90.git11486/scripts/find-lang.sh.no-man-dirs 2012-03-07 11:31:10.000000000 +0200 ++++ rpm-4.9.90.git11486/scripts/find-lang.sh 2012-03-07 15:11:57.465801075 +0200 +@@ -181,7 +181,7 @@ s:%lang(C) :: + find "$TOP_DIR" -type d|sed ' + s:'"$TOP_DIR"':: + '"$ALL_NAME$MAN"'s:\(.*/man/\([^/_]\+\).*/man[a-z0-9]\+/\):: +-'"$ALL_NAME$MAN"'s:\(.*/man/\([^/_]\+\).*/man[a-z0-9]\+$\):%lang(\2) \1*: ++'"$ALL_NAME$MAN"'s:\(.*/man/\([^/_]\+\).*/man[a-z0-9]\+$\):%lang(\2) \1/*: + s:^\([^%].*\):: + s:%lang(C) :: + /^$/d' >> $MO_NAME diff --git a/SOURCES/rpmdb-rebuild.service b/SOURCES/rpmdb-rebuild.service new file mode 100644 index 0000000..0580adb --- /dev/null +++ b/SOURCES/rpmdb-rebuild.service @@ -0,0 +1,19 @@ +[Unit] +Description=RPM database rebuild +ConditionPathExists=/var/lib/rpm/.rebuilddb + +# This should run before any daemons that may open the rpmdb +DefaultDependencies=no +After=sysinit.target +Before=basic.target shutdown.target +Conflicts=shutdown.target +# In case /var is remote-mounted +RequiresMountsFor=/var + +[Service] +Type=oneshot +ExecStart=/usr/bin/rpmdb --rebuilddb +ExecStartPost=rm -f /var/lib/rpm/.rebuilddb + +[Install] +WantedBy=basic.target diff --git a/SPECS/rpm.spec b/SPECS/rpm.spec new file mode 100644 index 0000000..c864f79 --- /dev/null +++ b/SPECS/rpm.spec @@ -0,0 +1,1117 @@ + +# run internal testsuite? +# fakechroot is severely broken beyond fedora 33, disable... +%if 0%{?fedora} > 33 || 0%{?rhel} > 8 +%bcond_with check +%else +%bcond_without check +%endif + +# build against xz? +%bcond_without xz +# build with plugins? +%bcond_without plugins +# build with libarchive? (needed for rpm2archive) +%bcond_without libarchive +# build with libimaevm.so +%bcond_without libimaevm +# build with zstd support? +%bcond_without zstd +# build with ndb backend? +%bcond_without ndb +# build with sqlite support? +%bcond_without sqlite +# build with bdb support? +%bcond_with bdb +# build with internal Berkeley DB? +%bcond_with int_bdb +# build with bdb_ro support? +%bcond_without bdb_ro + +%define rpmhome /usr/lib/rpm + +%global rpmver 4.16.1.3 +#global snapver rc1 +%global rel 12 +%global sover 9 + +%global srcver %{rpmver}%{?snapver:-%{snapver}} +%global srcdir %{?snapver:testing}%{!?snapver:rpm-%(echo %{rpmver} | cut -d'.' -f1-2).x} + +%if %{with bdb} +%define bdbver 5.3.15 + +# Build-dependency on systemd for the sake of one macro would be a bit much... +%{!?_tmpfilesdir:%global _tmpfilesdir /usr/lib/tmpfiles.d} +%endif + +Summary: The RPM package management system +Name: rpm +Version: %{rpmver} +Release: %{?snapver:0.%{snapver}.}%{rel}%{?dist} +Url: http://www.rpm.org/ +Source0: http://ftp.rpm.org/releases/%{srcdir}/rpm-%{srcver}.tar.bz2 +%if %{with bdb} && %{with int_bdb} +Source1: db-%{bdbver}.tar.gz +%endif + +Source10: rpmdb-rebuild.service + +# Disable autoconf config.site processing (#962837) +Patch1: rpm-4.15.x-siteconfig.patch +# In current Fedora, man-pages pkg owns all the localized man directories +Patch3: rpm-4.9.90-no-man-dirs.patch +# Temporary band-aid for rpm2cpio whining on payload size mismatch (#1142949) +Patch5: rpm-4.12.0-rpm2cpio-hack.patch +# https://github.com/rpm-software-management/rpm/pull/473 +Patch6: 0001-find-debuginfo.sh-decompress-DWARF-compressed-ELF-se.patch +Patch7: 0001-Issue-deprecation-warning-when-creating-BDB-database.patch + +# Patches already upstream: +Patch100: rpm-4.16.1.3-imp-covscan-fixes.patch +Patch101: rpm-4.16.1.3-rpmsign-support-EdDSA-sig.patch +Patch102: rpm-4.16.1.3-add-fapolicyd-plugin.patch +Patch103: rpm-4.16.1.3-unblock-signals-in-forked-scriptlets.patch +Patch104: rpm-4.16.1.3-support-bdb-hash-v8.patch +Patch105: rpm-4.16.1.3-ELF-files-strip-when-debuginfo-disabled.patch +Patch106: rpm-4.16.1.3-unbreak-checking-of-installed-rich-deps.patch +Patch107: rpm-4.16.1.3-fix-IMA-sig-len-assumed-const.patch +Patch108: rpm-4.16.1.3-validate-and-require-subkey-binding-sigs.patch +Patch109: rpm-4.16.1.3-bump-rpmdb-cookie-hash-to-SHA256-for-FIPS.patch +Patch110: rpm-4.16.1.3-add-path-query-option.patch +Patch111: rpm-4.16.1.3-skip-recorded-symlinks-in-setperms.patch +Patch112: rpm-4.16.1.3-fix-regression-reading-rpm-v3-pkgs.patch +Patch113: rpm-4.16.1.3-fix-spurious-transfiletriggerpostun-execution.patch + +# These are not yet upstream +Patch906: rpm-4.7.1-geode-i686.patch +# Probably to be upstreamed in slightly different form +Patch907: rpm-4.15.x-ldflags.patch + +# Not yet (all) upstream, debugedit DWARF5 +# https://code.wildebeest.org/git/user/mjw/rpm/log/?h=gcc-dwarf5-4.16.1.2 +Patch911: 0001-NFC-debugedit-Protect-macro-arguments-by-parentheses.patch +Patch912: 0002-NFC-debugedit-Move-code-from-edit_dwarf2-to-edit_inf.patch +Patch913: 0003-debugedit-Fix-missing-relocation-of-.debug_types-sec.patch +Patch914: 0004-NFC-debugedit-Move-code-to-separate-functions.patch +Patch915: 0005-debugedit-Implement-DWARF-5-unit-header-and-new-form.patch +Patch916: 0006-debugedit-Handle-DWARF-5-debug_line-and-debug_line_s.patch + +# Downstream-only patches +Patch1000: rpm-4.16.1.3-hashtab-use-after-free-fix.patch + +# Partially GPL/LGPL dual-licensed and some bits with BSD +# SourceLicense: (GPLv2+ and LGPLv2+ with exceptions) and BSD +License: GPLv2+ + +Requires: coreutils +Requires: popt%{_isa} >= 1.10.2.1 +Requires: curl +Obsoletes: python2-rpm < %{version}-%{release} + +%if %{with bdb} && %{without int_bdb} +BuildRequires: libdb-devel +%endif + +%if %{with check} +BuildRequires: fakechroot gnupg2 +%endif + +# XXX generally assumed to be installed but make it explicit as rpm +# is a bit special... +BuildRequires: redhat-rpm-config >= 94 +BuildRequires: systemd-rpm-macros +BuildRequires: gcc make +BuildRequires: gawk +BuildRequires: elfutils-devel >= 0.112 +BuildRequires: elfutils-libelf-devel +BuildRequires: readline-devel zlib-devel +BuildRequires: openssl-devel +# The popt version here just documents an older known-good version +BuildRequires: popt-devel >= 1.10.2 +BuildRequires: file-devel +BuildRequires: gettext-devel +BuildRequires: ncurses-devel +BuildRequires: bzip2-devel >= 0.9.0c-2 +BuildRequires: lua-devel >= 5.1 +BuildRequires: libcap-devel +BuildRequires: libacl-devel +%if %{with xz} +BuildRequires: xz-devel >= 4.999.8 +%endif +%if %{with libarchive} +BuildRequires: libarchive-devel +%endif +%if %{with zstd} +BuildRequires: libzstd-devel +%endif +%if %{with sqlite} +BuildRequires: sqlite-devel +%endif +# Couple of patches change makefiles so, require for now... +BuildRequires: automake libtool + +%if %{with plugins} +BuildRequires: libselinux-devel +BuildRequires: dbus-devel +BuildRequires: audit-libs-devel +%endif + +%if %{with libimaevm} +BuildRequires: ima-evm-utils-devel >= 1.0 +%endif + +%description +The RPM Package Manager (RPM) is a powerful command line driven +package management system capable of installing, uninstalling, +verifying, querying, and updating software packages. Each software +package consists of an archive of files along with information about +the package like its version, a description, etc. + +%package libs +Summary: Libraries for manipulating RPM packages +License: GPLv2+ and LGPLv2+ with exceptions +Requires: %{name} = %{version}-%{release} + +%description libs +This package contains the RPM shared libraries. + +%package build-libs +Summary: Libraries for building RPM packages +License: GPLv2+ and LGPLv2+ with exceptions +Requires: rpm-libs%{_isa} = %{version}-%{release} + +%description build-libs +This package contains the RPM shared libraries for building packages. + +%package sign-libs +Summary: Libraries for signing RPM packages +License: GPLv2+ and LGPLv2+ with exceptions +Requires: rpm-libs%{_isa} = %{version}-%{release} +Requires: %{_bindir}/gpg2 + +%description sign-libs +This package contains the RPM shared libraries for signing packages. + +%package devel +Summary: Development files for manipulating RPM packages +License: GPLv2+ and LGPLv2+ with exceptions +Requires: %{name} = %{version}-%{release} +Requires: %{name}-libs%{_isa} = %{version}-%{release} +Requires: %{name}-build-libs%{_isa} = %{version}-%{release} +Requires: %{name}-sign-libs%{_isa} = %{version}-%{release} +Requires: popt-devel%{_isa} + +%description devel +This package contains the RPM C library and header files. These +development files will simplify the process of writing programs that +manipulate RPM packages and databases. These files are intended to +simplify the process of creating graphical package managers or any +other tools that need an intimate knowledge of RPM packages in order +to function. + +This package should be installed if you want to develop programs that +will manipulate RPM packages and databases. + +%package build +Summary: Scripts and executable programs used to build packages +Requires: rpm = %{version}-%{release} +Requires: elfutils >= 0.128 binutils +Requires: findutils sed grep gawk diffutils file patch >= 2.5 +Requires: tar unzip gzip bzip2 cpio xz +%if %{with zstd} +Requires: zstd +%endif +Requires: pkgconfig >= 1:0.24 +Requires: /usr/bin/gdb-add-index +# https://fedoraproject.org/wiki/Changes/Minimal_GDB_in_buildroot +Suggests: gdb-minimal +# Technically rpmbuild doesn't require any external configuration, but +# creating distro-compatible packages does. To make the common case +# "just work" while allowing for alternatives, depend on a virtual +# provide, typically coming from redhat-rpm-config. +Requires: system-rpm-config + +%description build +The rpm-build package contains the scripts and executable programs +that are used to build packages using the RPM Package Manager. + +%package sign +Summary: Package signing support +Requires: rpm-sign-libs%{_isa} = %{version}-%{release} + +%description sign +This package contains support for digitally signing RPM packages. + +%package -n python3-%{name} +Summary: Python 3 bindings for apps which will manipulate RPM packages +BuildRequires: python3-devel +%{?python_provide:%python_provide python3-%{name}} +Requires: %{name}-libs%{?_isa} = %{version}-%{release} +Provides: %{name}-python3 = %{version}-%{release} +Obsoletes: %{name}-python3 < %{version}-%{release} +Obsoletes: platform-python-%{name} < %{version}-%{release} + +%description -n python3-%{name} +The python3-rpm package contains a module that permits applications +written in the Python programming language to use the interface +supplied by RPM Package Manager libraries. + +This package should be installed if you want to develop Python 3 +programs that will manipulate RPM packages and databases. + +%package apidocs +Summary: API documentation for RPM libraries +BuildArch: noarch + +%description apidocs +This package contains API documentation for developing applications +that will manipulate RPM packages and databases. + +%package cron +Summary: Create daily logs of installed packages. +BuildArch: noarch +Requires: crontabs logrotate rpm = %{version}-%{release} + +%description cron +This package contains a cron job which creates daily logs of installed +packages on a system. + +%if %{with plugins} +%package plugin-selinux +Summary: Rpm plugin for SELinux functionality +Requires: rpm-libs%{_isa} = %{version}-%{release} +Requires: selinux-policy-base + +%description plugin-selinux +%{summary}. + +%package plugin-syslog +Summary: Rpm plugin for syslog functionality +Requires: rpm-libs%{_isa} = %{version}-%{release} + +%description plugin-syslog +%{summary}. + +%package plugin-systemd-inhibit +Summary: Rpm plugin for systemd inhibit functionality +Requires: rpm-libs%{_isa} = %{version}-%{release} + +%description plugin-systemd-inhibit +This plugin blocks systemd from entering idle, sleep or shutdown while an rpm +transaction is running using the systemd-inhibit mechanism. + +%package plugin-ima +Summary: Rpm plugin ima file signatures +Requires: rpm-libs%{_isa} = %{version}-%{release} + +%description plugin-ima +%{summary}. + +%package plugin-fapolicyd +Summary: Rpm plugin for fapolicyd functionality +Requires: rpm-libs%{_isa} = %{version}-%{release} +Provides: fapolicyd-plugin +Obsoletes: fapolicyd-dnf-plugin + +%description plugin-fapolicyd +%{summary}. + +%package plugin-prioreset +Summary: Rpm plugin for resetting scriptlet priorities for SysV init +Requires: rpm-libs%{_isa} = %{version}-%{release} + +%description plugin-prioreset +%{summary}. + +Useful on legacy SysV init systems if you run rpm transactions with +nice/ionice priorities. Should not be used on systemd systems. + +%package plugin-audit +Summary: Rpm plugin for logging audit events on package operations +Requires: rpm-libs%{_isa} = %{version}-%{release} + +%description plugin-audit +%{summary}. + +# with plugins +%endif + +%prep +%autosetup -n rpm-%{srcver} %{?with_int_bdb:-a 1} -p1 + +%if %{with bdb} && %{with int_bdb} +ln -s db-%{bdbver} db +%endif + +# switch to sqlite db by default, including during build-time tests +%if %{with sqlite} +sed -i -e "/_db_backend/ s/ bdb/ sqlite/g" macros.in +%endif + +%build +%set_build_flags + +autoreconf -i -f + +# Hardening hack taken from macro %%configure defined in redhat-rpm-config +for i in $(find . -name ltmain.sh) ; do + %{__sed} -i.backup -e 's~compiler_flags=$~compiler_flags="%{_hardened_ldflags}"~' $i +done; + +# Using configure macro has some unwanted side-effects on rpm platform +# setup, use the old-fashioned way for now only defining minimal paths. +./configure \ + --prefix=%{_usr} \ + --sysconfdir=%{_sysconfdir} \ + --localstatedir=%{_var} \ + --sharedstatedir=%{_var}/lib \ + --libdir=%{_libdir} \ + --build=%{_target_platform} \ + --host=%{_target_platform} \ + --with-vendor=redhat \ + --enable-bdb=%{?with_bdb:yes}%{!?with_bdb:no} \ + %{!?with_int_bdb: --with-external-db} \ + %{!?with_plugins: --disable-plugins} \ + --with-lua \ + --with-selinux \ + --with-cap \ + --with-acl \ + %{?with_ndb: --enable-ndb} \ + %{!?with_libarchive: --without-archive} \ + %{?with_libimaevm: --with-imaevm} \ + %{?with_zstd: --enable-zstd} \ + %{?with_sqlite: --enable-sqlite} \ + %{?with_bdb_ro: --enable-bdb-ro} \ + --with-fapolicyd \ + --enable-python \ + --with-crypto=openssl + +%make_build + +pushd python +%py3_build +popd + +%install +%make_install + +# We need to build with --enable-python for the self-test suite, but we +# actually package the bindings built with setup.py (#531543#c26) +pushd python +%py3_install +popd + +mkdir -p $RPM_BUILD_ROOT%{_unitdir} +install -m 644 %{SOURCE10} $RPM_BUILD_ROOT/%{_unitdir} + +# Save list of packages through cron +mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/cron.daily +install -m 755 scripts/rpm.daily ${RPM_BUILD_ROOT}%{_sysconfdir}/cron.daily/rpm + +mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d +install -m 644 scripts/rpm.log ${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d/rpm + +%if %{with bdb} +mkdir -p ${RPM_BUILD_ROOT}%{_tmpfilesdir} +echo "r /var/lib/rpm/__db.*" > ${RPM_BUILD_ROOT}%{_tmpfilesdir}/rpm.conf +%endif + +mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/rpm +mkdir -p $RPM_BUILD_ROOT%{rpmhome}/macros.d +mkdir -p $RPM_BUILD_ROOT/var/lib/rpm + +# init an empty database for %ghost'ing for all supported backends +for be in %{?with_ndb:ndb} %{?with_sqlite:sqlite} %{?with_bdb:bdb}; do + ./rpmdb --define "_db_backend ${be}" --dbpath=${PWD}/${be} --initdb + cp -va ${be}/. $RPM_BUILD_ROOT/var/lib/rpm/ +done + +%find_lang rpm + +find $RPM_BUILD_ROOT -name "*.la"|xargs rm -f + +# These live in perl-generators and python-rpm-generators now +rm -f $RPM_BUILD_ROOT/%{rpmhome}/{perldeps.pl,perl.*,pythond*} +rm -f $RPM_BUILD_ROOT/%{_fileattrsdir}/{perl*,python*} +rm -rf $RPM_BUILD_ROOT/var/tmp + +%if %{with check} +%check +make check TESTSUITEFLAGS=-j%{_smp_build_ncpus} || (cat tests/rpmtests.log; exit 1) +# rpm >= 4.16.0 testsuite leaves a read-only tree behind, clean it up +make clean +%endif + +# Handle rpmdb rebuild service on erasure of old to avoid ordering issues +# https://pagure.io/fesco/issue/2382 +%triggerun -- rpm < 4.15.90-0.git14971.10 +if [ -x /usr/bin/systemctl ]; then + systemctl --no-reload preset rpmdb-rebuild ||: +fi + +%posttrans +if [ -f /var/lib/rpm/Packages ]; then + touch /var/lib/rpm/.rebuilddb +fi + +%files -f rpm.lang +%license COPYING +%doc CREDITS doc/manual/[a-z]* + +%if %{with bdb} +%{_tmpfilesdir}/rpm.conf +%endif + +%{_unitdir}/rpmdb-rebuild.service + +%dir %{_sysconfdir}/rpm + +%attr(0755, root, root) %dir /var/lib/rpm +%attr(0644, root, root) %ghost %config(missingok,noreplace) /var/lib/rpm/* +%attr(0644, root, root) %ghost /var/lib/rpm/.*.lock + +%{_bindir}/rpm +%if %{with libarchive} +%{_bindir}/rpm2archive +%endif +%{_bindir}/rpm2cpio +%{_bindir}/rpmdb +%{_bindir}/rpmkeys +%{_bindir}/rpmquery +%{_bindir}/rpmverify + +%{_mandir}/man8/rpm.8* +%{_mandir}/man8/rpmdb.8* +%{_mandir}/man8/rpmkeys.8* +%if %{with libarchive} +%{_mandir}/man8/rpm2archive.8* +%endif +%{_mandir}/man8/rpm2cpio.8* +%{_mandir}/man8/rpm-misc.8* +%{_mandir}/man8/rpm-plugins.8* + +# XXX this places translated manuals to wrong package wrt eg rpmbuild +%lang(fr) %{_mandir}/fr/man[18]/*.[18]* +%lang(ko) %{_mandir}/ko/man[18]/*.[18]* +%lang(ja) %{_mandir}/ja/man[18]/*.[18]* +%lang(pl) %{_mandir}/pl/man[18]/*.[18]* +%lang(ru) %{_mandir}/ru/man[18]/*.[18]* +%lang(sk) %{_mandir}/sk/man[18]/*.[18]* + +%attr(0755, root, root) %dir %{rpmhome} +%{rpmhome}/macros +%{rpmhome}/macros.d +%{rpmhome}/lua +%{rpmhome}/rpmpopt* +%{rpmhome}/rpmrc + +%{rpmhome}/rpmdb_* +%{rpmhome}/rpm.daily +%{rpmhome}/rpm.log +%{rpmhome}/rpm.supp +%{rpmhome}/rpm2cpio.sh +%{rpmhome}/tgpg + +%{rpmhome}/platform + +%dir %{rpmhome}/fileattrs + +%files libs +%{_libdir}/librpmio.so.%{sover} +%{_libdir}/librpm.so.%{sover} +%{_libdir}/librpmio.so.%{sover}.* +%{_libdir}/librpm.so.%{sover}.* +%if %{with plugins} +%dir %{_libdir}/rpm-plugins + +%files plugin-syslog +%{_libdir}/rpm-plugins/syslog.so +%{_mandir}/man8/rpm-plugin-syslog.8* + +%files plugin-selinux +%{_libdir}/rpm-plugins/selinux.so +%{_mandir}/man8/rpm-plugin-selinux.8* + +%files plugin-systemd-inhibit +%{_libdir}/rpm-plugins/systemd_inhibit.so +%{_mandir}/man8/rpm-plugin-systemd-inhibit.8* + +%files plugin-ima +%{_libdir}/rpm-plugins/ima.so +%{_mandir}/man8/rpm-plugin-ima.8* + +%files plugin-fapolicyd +%{_libdir}/rpm-plugins/fapolicyd.so +%{_mandir}/man8/rpm-plugin-fapolicyd.8* + +%files plugin-prioreset +%{_libdir}/rpm-plugins/prioreset.so +%{_mandir}/man8/rpm-plugin-prioreset.8* + +%files plugin-audit +%{_libdir}/rpm-plugins/audit.so +%{_mandir}/man8/rpm-plugin-audit.8* +# with plugins +%endif + +%files build-libs +%{_libdir}/librpmbuild.so.%{sover} +%{_libdir}/librpmbuild.so.%{sover}.* + +%files sign-libs +%{_libdir}/librpmsign.so.%{sover} +%{_libdir}/librpmsign.so.%{sover}.* + +%files build +%{_bindir}/rpmbuild +%{_bindir}/gendiff +%{_bindir}/rpmspec + +%{_mandir}/man1/gendiff.1* +%{_mandir}/man8/rpmbuild.8* +%{_mandir}/man8/rpmdeps.8* +%{_mandir}/man8/rpmspec.8* + +%{rpmhome}/brp-* +%{rpmhome}/check-* +%{rpmhome}/debugedit +%{rpmhome}/sepdebugcrcfix +%{rpmhome}/find-debuginfo.sh +%{rpmhome}/find-lang.sh +%{rpmhome}/*provides* +%{rpmhome}/*requires* +%{rpmhome}/*deps* +%{rpmhome}/*.prov +%{rpmhome}/*.req +%{rpmhome}/mkinstalldirs +%{rpmhome}/fileattrs/* + +%files sign +%{_bindir}/rpmsign +%{_mandir}/man8/rpmsign.8* + +%files -n python3-%{name} +%{python3_sitearch}/rpm/ +%{python3_sitearch}/rpm-%{rpmver}*.egg-info + +%files devel +%{_mandir}/man8/rpmgraph.8* +%{_bindir}/rpmgraph +%{_libdir}/librp*[a-z].so +%{_libdir}/pkgconfig/rpm.pc +%{_includedir}/rpm/ + +%files cron +%{_sysconfdir}/cron.daily/rpm +%config(noreplace) %{_sysconfdir}/logrotate.d/rpm + +%files apidocs +%license COPYING +%doc doc/librpm/html/* + +%changelog +* Tue Apr 05 2022 Michal Domonkos - 4.16.1.3-12 +- Fix minor ABI regression in rpmcli.h (#2037352) + +* Mon Feb 14 2022 Michal Domonkos - 4.16.1.3-11 +- Fix IMA signature lengths assumed constant, take III (#2018937) +- Fix regression reading rpm v3 and other rare packages (#2037186) +- Fix spurious %transfiletriggerpostun execution (#2023692) + +* Mon Jan 31 2022 Michal Domonkos - 4.16.1.3-10 +- Address covscan issues in binding sigs validation patch (#1943724) +- Bump hash for rpmdb cookie to SHA256 for FIPS (#2048455) +- Add --path query option (#2037352) +- Skip recorded symlinks in --setperms (#2025906) + +* Mon Dec 13 2021 Michal Domonkos - 4.16.1.3-9 +- Fix IMA signature lengths assumed constant, take II (#2018937) + +* Thu Dec 09 2021 Michal Domonkos - 4.16.1.3-8 +- Support hash v8 databases from BDB < 4.6 (#1965147) +- Ensure ELF files get stripped when debuginfo is disabled (#1999009) +- Actually honor libarchive bcond at configure time (#1999012) +- Unbreak checking of installed rich dependencies (#2015407) +- Rebuild against soname bump in ima-evm-utils (#2026079) +- Fix IMA signature lengths assumed constant (#2018937) +- Validate and require subkey binding sigs on PGP pubkeys (#1943724) +- Fixes CVE-2021-3521 + +* Thu Aug 19 2021 Michal Domonkos - 4.16.1.3-7 +- Unblock signals in forked scriptlets (#1991667) + +* Tue Aug 10 2021 Mohan Boddu - 4.16.1.3-6.1 +- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags + Related: rhbz#1991688 + +* Wed Jul 28 2021 Florian Weimer - 4.16.1.3-6 +- Rebuild to pick up OpenSSL 3.0 Beta ABI (#1984097) + +* Fri Jul 23 2021 Michal Domonkos - 4.16.1.3-5 +- Rebuild for gating.yaml + +* Thu Jul 22 2021 Michal Domonkos - 4.16.1.3-4 +- Add support for EdDSA signatures to rpmsign (#1962234) +- Add fapolicyd plugin (#1942549) + +* Mon Jul 12 2021 Michal Domonkos - 4.16.1.3-3 +- Release bump for a rebuild + +* Tue Jun 29 2021 Michal Domonkos - 4.16.1.3-2 +- Address important covscan issues (#1938861) + +* Tue Jun 15 2021 Mohan Boddu - 4.16.1.3-1.2 +- Rebuilt for RHEL 9 BETA for openssl 3.0. Related: rhbz#1971065 + +* Fri Apr 16 2021 Mohan Boddu - 4.16.1.3-1.1 +- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937 + +* Mon Mar 22 2021 Panu Matilainen - 4.16.1.3-1 +- Rebase to rpm 4.16.1.3 (https://rpm.org/wiki/Releases/4.16.1.3) + +* Wed Feb 03 2021 Panu Matilainen - 4.16.1.2-6 +- Drop support for read-write Berkeley DB format (#1787311) + +* Wed Feb 03 2021 Panu Matilainen - 4.16.1.2-5 +- Make with/without bdb build option actually work +- Clean up unpackaged /var/tmp from the build root + +* Wed Jan 27 2021 Fedora Release Engineering - 4.16.1.2-4.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Fri Jan 22 2021 Mark Wielaard - 4.16.1.2-4 +- Fix edit_attributes_str_comp_dir in Patch916 (#1919107) + +* Tue Jan 19 2021 Jeff Law - 4.16.1.2-3 +- Fix typo in test for F33 or newer + +* Tue Jan 19 2021 Mark Wielaard - 4.16.1.2-2 +- Add debugedit DWARF5 support + +* Wed Dec 16 2020 Panu Matilainen - 4.16.1.2-1 +- Rebase to rpm 4.16.1.2 (http://rpm.org/wiki/Releases/4.16.1.2) +- Add a spec safeguard for accidental soname bumps + +* Wed Dec 16 2020 Panu Matilainen - 4.16.1.1-1 +- Rebase to rpm 4.16.1.1 (http://rpm.org/wiki/Releases/4.16.1.1) + +* Thu Dec 10 2020 Panu Matilainen - 4.16.1-1 +- Rebase to rpm 4.16.1 (http://rpm.org/wiki/Releases/4.16.1) + +* Mon Nov 30 2020 Panu Matilainen - 4.16.0-5 +- Only disable test-suite where it's actually broken + +* Mon Nov 30 2020 Panu Matilainen - 4.16.0-4 +- Fix BDB crashing on failed open attempts (#1902395, #1898299, #1900407) +- Fix unnecessary double failure on lazy keyring open + +* Wed Oct 28 2020 Panu Matilainen - 4.16.0-3 +- Issue deprecation warning when creating BDB databases (#1787311) +- Temporarily disable test-suite due to massive fakechroot breakage + +* Mon Oct 05 2020 Panu Matilainen - 4.16.0-2 +- Clean up after test-suite which leaves a read-only tree behind + +* Wed Sep 30 2020 Panu Matilainen - 4.16.0-1 +- Rebase to 4.16.0 final (https://rpm.org/wiki/Releases/4.16.0) + +* Mon Aug 31 2020 Panu Matilainen - 4.16.0-0.rc1.1 +- Rebase to 4.16.0-rc1 +- Run test-suite in parallel + +* Sat Aug 01 2020 Fedora Release Engineering - 4.16.0-0.beta3.2.3 +- Second attempt - Rebuilt for + https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Wed Jul 29 2020 Fedora Release Engineering - 4.16.0-0.beta3.2.2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Sun Jul 26 2020 Peter Robinson - 4.16.0-0.beta3.2.1 +- rebuild for ima-evm-utils 1.3 + +* Mon Jun 29 2020 Tom Callaway - 4.16.0-0.beta3.2 +- rebuild for lua 5.4 + +* Wed Jun 24 2020 Panu Matilainen - 4.16.0-0.beta3.1 +- Rebase to beta3 + +* Wed Jun 10 2020 Panu Matilainen - 4.16.0-0.beta1.4 +- Fix prefix search on sqlite backend (many file triggers not running) + +* Mon Jun 8 2020 Panu Matilainen - 4.16.0-0.beta1.3 +- Unbreak metainfo() provide generation + +* Wed Jun 3 2020 Panu Matilainen - 4.16.0-0.beta1.2 +- Don't auto-enable _flush_io on non-rotational media, it's too costly + +* Mon Jun 1 2020 Panu Matilainen - 4.16.0-0.beta1.1 +- Rebase to rpm 4.16.0-beta1 + +* Fri May 22 2020 Miro Hrončok - 4.15.90-0.git14971.12.1 +- Rebuilt for Python 3.9 + +* Tue May 12 2020 Panu Matilainen - 4.15.90-0.git14971.12 +- Fix segfault when trying to use unknown database backend + +* Thu May 7 2020 Panu Matilainen - 4.15.90-0.git14971.11 +- Flag BDB databases for rebuild on next reboot whenever rpm is updated +- Switch default database to sqlite (#1818910) + +* Mon May 4 2020 Panu Matilainen - 4.15.90-0.git14971.10 +- Handle rpmdb-rebuild service enablement for upgrades + +* Thu Apr 23 2020 Panu Matilainen - 4.15.90-0.git14971.9 +- Fix questionable uses of %%{name} and %%{version} in the spec + +* Wed Apr 22 2020 Panu Matilainen - 4.15.90-0.git14971.8 +- Fix regression(s) on build dependency resolution + +* Wed Apr 22 2020 Panu Matilainen - 4.15.90-0.git14971.7 +- Add rpmdb-rebuild systemd service + +* Fri Apr 17 2020 Panu Matilainen - 4.15.90-0.git14971.6 +- Warn on undefined macros in buildtree setup macros (#1820349) + +* Thu Apr 09 2020 Panu Matilainen - 4.15.90-0.git14971.5 +- Fix regression causing all ELF files classified as OCaml + +* Mon Apr 06 2020 Panu Matilainen - 4.15.90-0.git14971.4 +- Fix invalid path passed to parametric macro generators + +* Thu Apr 02 2020 Panu Matilainen - 4.15.90-0.git14971.3 +- Fix db lock files not getting packaged + +* Tue Mar 31 2020 Panu Matilainen - 4.15.90-0.git14971.2 +- Move bdb specific systemd-tmpfiles cleanup crutch behind the bdb bcond + +* Tue Mar 31 2020 Panu Matilainen - 4.15.90-0.git14971.1 +- Rebase to rpm 4.16 alpha (https://rpm.org/wiki/Releases/4.16.0) +- Add bconds for and enable sqlite, ndb and bdb_ro database backends +- Add bcond for disabling bdb backend +- Drop lmdb bcond, the backend was removed upstream +- Ensure all database backend files are owned +- Fix external environment causing test-suite failures in spec build +- Re-enable hard test-suite failures again + +* Thu Jan 30 2020 Fedora Release Engineering - 4.15.1-2.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Thu Jan 9 2020 Panu Matilainen - 4.15.1-2 +- Obsolete python2-rpm to fix upgrade path (#1775113) + +* Mon Nov 18 2019 Panu Matilainen - 4.15.1-1 +- Rebase to 4.15.1 (https://rpm.org/wiki/Releases/4.15.1) + +* Thu Nov 14 2019 Adam Williamson - 4.15.0-7 +- Really revert armv8 detection improvements (patch was not applied in -6) + +* Wed Oct 23 2019 Peter Robinson 4.15.0-6 +- Revert armv8 detection improvements + +* Mon Oct 21 2019 Stephen Gallagher - 4.15.0-5 +- Revert aliasing arm64 to aarch64 +- Resolves: rhbz#1763831 + +* Fri Oct 18 2019 Panu Matilainen - 4.15.0-4 +- Revert problematic sub-variants of armv8 (#1691430) + +* Thu Oct 17 2019 Panu Matilainen - 4.15.0-3 +- Drop python2 bindings for good (#1761211) + +* Tue Oct 15 2019 Adam Williamson - 4.15.0-2 +- Revert systemd inhibit plugin's calling of dbus_shutdown (#1750575) + +* Thu Sep 26 2019 Panu Matilainen - 4.15.0-1 +- Update to 4.15.0 final (https://rpm.org/wiki/Releases/4.15.0) + +* Wed Aug 28 2019 Panu Matilainen - 4.15.0-0.rc1.1 +- Update to 4.15.0-rc1 + +* Tue Aug 27 2019 Panu Matilainen - 4.15.0-0.beta.6 +- Fix some issues in the thread cap logic + +* Mon Aug 26 2019 Panu Matilainen - 4.15.0-0.beta.5 +- Re-enable test-suite, temporarily disabled during alpha troubleshooting + +* Fri Aug 23 2019 Panu Matilainen - 4.15.0-0.beta.4 +- Cap number of threads on 32bit platforms (#1729382) +- Drop %%_lto_cflags macro (reverted upstream) + +* Fri Aug 23 2019 Panu Matilainen - 4.15.0-0.beta.3 +- Restore strict order of build scriptlet stdout/stderr output + +* Thu Aug 15 2019 Miro Hrončok - 4.15.0-0.beta.2.3 +- Rebuilt for Python 3.8 + +* Wed Jul 31 2019 Miro Hrončok - 4.15.0-0.beta.2.2 +- Rebuilt for libimaevm.so.1 + +* Fri Jul 26 2019 Fedora Release Engineering - 4.15.0-0.beta.2.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Sat Jul 20 18:30:10 CEST 2019 Igor Gnatenko - 4.15.0-0.beta.2 +- Backport patch to not set RPMTAG_BUILDTIME to SOURCE_DATE_EPOCH + +* Thu Jun 27 2019 Panu Matilainen - 4.15.0-0.beta.1 +- Rebase to 4.15.0 beta + +* Thu Jun 20 2019 Panu Matilainen - 4.14.90-0.git14653.18 +- Fix excessive TLS use, part II (#1722181) + +* Thu Jun 20 2019 Panu Matilainen - 4.14.90-0.git14653.17 +- Fix excessive TLS use (#1722181) + +* Wed Jun 19 2019 Panu Matilainen - 4.14.90-0.git14653.16 +- Drop buildarch again now that python_provide no longer needs it (#1720139) + +* Fri Jun 14 2019 Panu Matilainen - 4.14.90-0.git14653.15 +- Temporarily re-enable buildarch macro for python_provide macro use (#1720139) + +* Thu Jun 13 2019 Panu Matilainen - 4.14.90-0.git14653.14 +- Don't fail build trying to kill a non-existent process (#1720143) + +* Tue Jun 11 14:59:16 CEST 2019 Igor Gnatenko - 4.14.90-0.git14653.13 +- Fix build of binary packages in parallel + +* Tue Jun 11 00:08:50 CEST 2019 Igor Gnatenko - 4.14.90-0.git14653.10 +- Revert generation of binary packages in parallel + +* Mon Jun 10 2019 Panu Matilainen - 4.14.90-0.git14653.1 +- Update to 4.15.0 alpha + +* Mon Jun 10 2019 Panu Matilainen - 4.14.2.1-14 +- Drop support for sanitizer build, it never really worked anyway +- Drop leftover build-dependency on binutils-devel +- Truncate changelog to rpm 4.14.x (last two years) + +* Mon Jun 10 2019 Panu Matilainen - 4.14.2.1-13 +- Drop support for Fedora < 28 builds +- Drop leftover BDB-related compiler flag foo + +* Fri Jun 07 2019 Panu Matilainen - 4.14.2.1-12 +- Use pre-determined buildhost in test-suite to avoid DNS usage +- Drop obsolete specspo and gpg2 related patches + +* Fri Jun 07 2019 Igor Gnatenko - 4.14.2.1-11 +- Use py2/3 macros for building and installing the bindings + +* Tue May 21 2019 Panu Matilainen - 4.14.2.1-10 +- Support build-id generation from compressed ELF files (#1650072) + +* Fri May 03 2019 Igor Gnatenko - 4.14.2.1-9 +- Suggest gdb-minimal + +* Thu Apr 25 2019 Panu Matilainen - 4.14.2.1-8 +- Replace deprecated __global_ldflags uses with build_ldflags macro + +* Thu Apr 11 2019 Panu Matilainen - 4.14.2.1-7 +- Fix excessive reference counting on faked string .decode() + +* Wed Apr 10 2019 Panu Matilainen - 4.14.2.1-6 +- Unbreak Python 3 API by returning string data as surrogate-escaped utf-8 + string objects instead of bytes (#1693751) +- As a temporary crutch, monkey-patch a .decode() method to returned strings + to give users time to migrate from the long-standing broken behavior + +* Wed Apr 10 2019 Panu Matilainen - 4.14.2.1-5 +- Generate minidebug for PIE executables on file >= 5.33 too +- Backport find-debuginfo --g-libs option for glibc's benefit (#1661512) + +* Sat Feb 02 2019 Fedora Release Engineering - 4.14.2.1-4.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Wed Dec 19 2018 Panu Matilainen - 4.14.2.1-4 +- Backport the new modularity label tag (#1650286) + +* Mon Nov 19 2018 Panu Matilainen - 4.14.2.1-3 +- Take prefix into account when compressing man pages etc for Flatpak builds + +* Wed Oct 24 2018 Panu Matilainen - 4.14.2.1-2 +- Selinux plugin requires a base policy to work (#1641631) + +* Mon Oct 22 2018 Panu Matilainen - 4.14.2.1-1 +- Rebase to rpm 4.14.2.1 (http://rpm.org/wiki/Releases/4.14.2.1) + +* Wed Oct 17 2018 Igor Gnatenko - 4.14.2-9 +- Push name/epoch/version/release macro before invoking depgens + +* Tue Oct 16 2018 Igor Gnatenko - 4.14.2-8 +- Resurrect long since broken Lua library path + +* Fri Oct 12 2018 Panu Matilainen - 4.14.2-7 +- Actually fail build on test-suite failures again +- Invoke python2 explicitly from test-suite to unbreak build, part II + +* Thu Oct 11 2018 Panu Matilainen - 4.14.2-6 +- Drop duplicate BDB buildrequire +- Drop nowadays unnecessary BDB macro foo +- Drop nowadays unnecessary manual libcap dependency + +* Thu Oct 11 2018 Panu Matilainen - 4.14.2-5 +- Own all rpmdb files and ensure the list remains up to date +- Drop redundant verify exclusions on rpmdb ghosts +- Fix build when systemd is not installed (duh) + +* Thu Oct 11 2018 Panu Matilainen - 4.14.2-4 +- Erm, really use the macro for tmpfiles.d path +- Erm, don't nuke buildroot at beginning of %%install +- Use modern build/install helper macros + +* Thu Oct 11 2018 Panu Matilainen - 4.14.2-3 +- Eh, selinux plugin dependency condition was upside down (#1493267) +- Drop no longer necessary condition over imaevm name +- Drop no longer necessary obsolete on compat-librpm3 + +* Thu Oct 11 2018 Panu Matilainen - 4.14.2-2 +- Fix ancient Python GIL locking bug (#1632488) +- Use the appropriate macro for tmpfiles.d now that one exists + +* Tue Aug 21 2018 Panu Matilainen - 4.14.2-1 +- Update to rpm 4.14.2 final (http://rpm.org/wiki/Releases/4.14.2) + +* Mon Aug 13 2018 Panu Matilainen - 4.14.2-0.rc2.2 +- Move python-macro-helper to main package where the macros are (#1577860) + +* Wed Aug 08 2018 Panu Matilainen - 4.14.2-0.rc2.1 +- Update to rpm 4.14.2-rc2 + +* Sat Jul 21 2018 Igor Gnatenko - 4.14.2-0.rc1.2 +- Decompress DWARF compressed ELF sections + +* Sat Jul 14 2018 Fedora Release Engineering - 4.14.2-0.rc1.1.2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Mon Jul 02 2018 Miro Hrončok - 4.14.2-0.rc1.1.1 +- Rebuilt for Python 3.7 + +* Fri Jun 29 2018 Panu Matilainen - 4.14.2-0.rc1.1 +- Update to rpm 4.14.2-rc1 +- Patching test-suite for python2 too painful, just sed it instead +- Fix premature version increment from previous changelog entries, oops + +* Fri Jun 29 2018 Panu Matilainen - 4.14.1-13 +- Ehm, need to patch the autogenerated rpmtests script too for python2 +- Ehm, it's ldconfig_scriptlets not scripts +- Drop the non-working python envvar magic from obsoleted change + +* Fri Jun 29 2018 Panu Matilainen - 4.14.1-12 +- Invoke python2 explicitly from test-suite to unbreak build + +* Fri Jun 29 2018 Panu Matilainen - 4.14.1-11 +- Remove direct ldconfig calls, use compat macros instead + +* Fri Jun 15 2018 Miro Hrončok - 4.14.1-10.1 +- Rebuilt for Python 3.7 + +* Mon May 28 2018 Miro Hrončok - 4.14.1-10 +- Backport upstream solution to make brp-python-bytecompile automagic part opt-outable + https://fedoraproject.org/wiki/Changes/No_more_automagic_Python_bytecompilation + +* Tue May 22 2018 Mark Wielaard - 4.14.1-9 +- find-debuginfo.sh: Handle application/x-pie-executable (#1581224) + +* Tue Feb 20 2018 Igor Gnatenko - 4.14.1-8 +- Split rpm-build-libs to one more subpackage rpm-sign-libs + +* Mon Feb 19 2018 Panu Matilainen - 4.14.1-7 +- Explicitly BuildRequire gcc and make + +* Fri Feb 09 2018 Igor Gnatenko - 4.14.1-6.1 +- Escape macros in %%changelog + +* Wed Jan 31 2018 Panu Matilainen - 4.14.1-6 +- Avoid unnecessary macro helper dependency on /usr/bin/python (#1538657) +- Fix release of previous changelog entry + +* Tue Jan 30 2018 Tomas Orsava - 4.14.1-5 +- Add envvar that will be present during RPM build, + Part of a Fedora Change for F28: "Avoid /usr/bin/python in RPM build" + https://fedoraproject.org/wiki/Changes/Avoid_usr_bin_python_in_RPM_Build + +* Tue Jan 30 2018 Petr Viktorin - 4.14.1-4 +- Skip automatic Python byte-compilation if *.py files are not present + +* Thu Jan 25 2018 Florian Weimer - 4.14.1-3 +- Rebuild to work around gcc bug leading to librpm miscompilation (#1538648) + +* Thu Jan 18 2018 Panu Matilainen - 4.14.1-2 +- Avoid nuking the new python-macro-helper along with dep generators (#1535692) + +* Tue Jan 16 2018 Panu Matilainen - 4.14.1-1 +- Rebase to rpm 4.14.1 (http://rpm.org/wiki/Releases/4.14.1) + +* Tue Nov 07 2017 Igor Gnatenko - 4.14.0-5 +- Fix typo in Obsoletes + +* Mon Nov 06 2017 Igor Gnatenko - 4.14.0-4 +- Remove platform-python bits + +* Thu Oct 26 2017 Panu Matilainen - 4.14.0-3 +- Move selinux plugin dependency to selinux-policy in Fedora >= 28 (#1493267) + +* Thu Oct 12 2017 Panu Matilainen - 4.14.0-2 +- Dump out test-suite log in case of failures again +- Don't assume per-user groups in test-suite + +* Thu Oct 12 2017 Panu Matilainen - 4.14.0-1 +- Rebase to rpm 4.14.0 final (http://rpm.org/wiki/Releases/4.14.0) + +* Tue Oct 10 2017 Troy Dawson - 4.14.0-0.rc2.6 +- Cleanup spec file conditionals + +* Tue Oct 03 2017 Panu Matilainen - 4.14.0-0.rc2.5 +- Add build conditionals for zstd and lmdb support +- Enable zstd support + +* Tue Oct 03 2017 Panu Matilainen - 4.14.0-0.rc2.4 +- Spec cleanups + +* Fri Sep 29 2017 Panu Matilainen - 4.14.0-0.rc2.3 +- BuildRequire gnupg2 for the testsuite + +* Fri Sep 29 2017 Panu Matilainen - 4.14.0-0.rc2.2 +- ima-evm-utils only has a -devel package in fedora >= 28 + +* Thu Sep 28 2017 Panu Matilainen - 4.14.0-0.rc2.1 +- Rebase to rpm 4.14.0-rc2 (http://rpm.org/wiki/Releases/4.14.0) + +* Mon Sep 18 2017 Panu Matilainen - 4.14.0-0.rc1.3 +- Fix Ftell() past 2GB on 32bit architectures (#1492587) + +* Thu Sep 07 2017 Panu Matilainen - 4.14.0-0.rc1.2 +- Actually honor with/without libimaevm option +- ima-evm-utils-devel >= 1.0 is required for rpm >= 4.14.0 + +* Wed Sep 06 2017 Panu Matilainen - 4.14.0-0.rc1.1 +- Rebase to rpm 4.14.0-rc1 (http://rpm.org/wiki/Releases/4.14.0) +- Re-enable SHA256 header digest generation (see #1480407) + +* Mon Aug 28 2017 Panu Matilainen - 4.13.90-0.git14000.8 +- Band-aid for DB_VERSION_MISMATCH errors on glibc updates (#1465809) + +* Thu Aug 24 2017 Panu Matilainen - 4.13.90-0.git14000.7 +- Remove ugly kludges from posttrans script, BDB handles this now + +* Fri Aug 18 2017 Panu Matilainen - 4.13.90-0.git14000.6 +- Silence harmless but bogus error message on noarch packages (#1482144) + +* Thu Aug 17 2017 Miro Hrončok - 4.13.90-0.git14002.5 +- Build with platform_python + +* Mon Aug 14 2017 Miro Hrončok - 4.13.90-0.git14000.4 +- Add platform-python bytecompilation patch: platform-python-bytecompile.patch +- Add platform python deps generator patch: platform-python-abi.patch +- Add a platform-python subpackage and remove system python related declarations +- Build rpm without platform_python for bytecompilation + (https://fedoraproject.org/wiki/Changes/Platform_Python_Stack) + +* Mon Aug 14 2017 Panu Matilainen - 4.13.90-0.git14000.3 +- Disable macro argument quoting as a band-aid to #1481025 + +* Fri Aug 11 2017 Panu Matilainen - 4.13.90-0.git14000.2 +- Disable SHA256 header-only digest generation temporarily (#1480407) + +* Thu Aug 10 2017 Panu Matilainen - 4.13.90-0.git14000.1 +- Rebase to rpm 4.13.90 aka 4.14.0-alpha (#1474836) +