I just fixed an rpmdb that db_dump into db_load would not repair.
Here are some random notes on what I did so I can find later:
The rpm failure symptom was:
# rpm -qa -vv
...
D: rpmdb: read h# 897 Header SHA1 digest: OK
(225a98efd2abd23e19a9baca1c67c9e75833b787)
DirectFB-0.9.25-29.i586
Segmentation fault
The root cause problem was:
# /usr/lib/rpm/db_verify /var/lib/rpm/Packages
db_verify: Page 5669: item 50 is out of order or nonsensical
db_verify: Packages: DB_VERIFY_BAD: Database verification failed
The usual
cd /var/lib/rpm
mv Packages Packages-ORIG
db_dump Packages-ORIG | db_load Packages
failed to repair the damage.
Deeper analysis showed that there was not only structural, but also
data,
damage of header instances.
This modest hack applied a sanity check on header instances, and skipped
damaged header instances:
Index: rpmdb.c
===================================================================
RCS file: /v/rpm/cvs/rpm/rpmdb/rpmdb.c,v
retrieving revision 1.244
diff -u -b -B -w -p -r1.244 rpmdb.c
--- rpmdb.c 12 Mar 2008 19:41:13 -0000 1.244
+++ rpmdb.c 20 Mar 2008 18:20:08 -0000
@@ -2402,6 +2402,10 @@ if (dbiByteSwapped(dbi) == 1)
if (rc || (mi->mi_setx && mi->mi_offset == 0))
return NULL;
/*@=compmempass@*/
+if (mi->mi_offset & 0xffff0000) {
+fprintf(stderr, "*** damaged key 0x%x reset to 0\n", mi->mi_offset);
+mi->mi_offset = 0;
+}
}
mi->mi_setx++;
} while (mi->mi_offset == 0);
With the hack applied, here's the damage that was exhibited:
[root@wellfleet rpm]# rpm -qa > /dev/null
*** damaged key 0x80000399 reset to 0
*** damaged key 0x808003f9 reset to 0
error: rpmdb: skipping h# 1164 Header SHA1 digest: BAD Expected
(3411a61f872094fd2ceb650f7317abb1a49022dc) !=
(237083ef497fcabaf510e7db4457d4d165a7967c)
error: rpmdb: skipping h# 1220 Header V3 DSA signature: BAD, key
ID 9c800aca
error: rpmdb: skipping h# 1287 Header V3 DSA signature: BAD, key
ID 9c800aca
error: rpmdb: skipping h# 1215 Header V3 DSA signature: BAD, key
ID 9c800aca
error: rpmdb: skipping h# 1223 Header V3 DSA signature: BAD, key
ID 9c800aca
error: rpmdb: skipping h# 1274 Header V3 DSA signature: BAD, key
ID 9c800aca
error: rpmdb: skipping h# 1077 Header V3 DSA signature: BAD, key
ID 6b9d6523
error: rpmdb: skipping h# 1217 Header V3 DSA signature: BAD, key
ID 9c800aca
error: rpmdb: skipping h# 1245 Header V3 DSA signature: BAD, key
ID 9a795806
*** damaged key 0x58000002 reset to 0
*** damaged key 0x30000019 reset to 0
error: rpmdb: skipping h# 1144 Header V3 DSA signature: BAD, key
ID 9c800aca
error: rpmdb: skipping h# 1216 Header V3 DSA signature: BAD, key
ID 9c800aca
error: rpmdb: skipping h# 1240 Header V3 DSA signature: BAD, key
ID 9a795806
error: rpmdb: skipping h# 1147 Header SHA1 digest: BAD Expected
(d7d4356d956f9d8d279b4ccb2b7236ff90bf6c4e) !=
(5b050cf3fe1023ecf9a41fdda31c99a1cd75b530)
error: rpmdb: skipping h# 1219 Header V3 DSA signature: BAD, key
ID 9c800aca
error: rpmdb: skipping h# 1328 Header V3 DSA signature: BAD, key
ID 9c800aca
An rpm --rebuilddb then saved what headers were not damaged, skipping
over the damage.
The damage was random and pathological and hardly worth avoiding
imho. Certainly
rpm (and rpmlib) did not do this damage.
However the hack could be done more carefully by retrieving the
largest known
header instance and using that as range check on header instances.
Otherwise,
its just a hack: there's lots of types of damage that would pass
through the
hack y sanity check without detection. Note that the more careful
check I mentioned
assumes that the range check is on a quiescent rpmdb, very much not
true for concurrent
rpmdb access in general.
Back to hacking ...
73 de Jeff
Received on Thu Mar 20 19:29:51 2008