summaryrefslogtreecommitdiff
path: root/lib/tdb
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2010-02-04 23:59:54 +1030
committerRusty Russell <rusty@rustcorp.com.au>2010-02-10 16:56:14 +1030
commitb37b452cb8c1f56b37b04abe7bffdede371ca361 (patch)
tree337e63a2be310ca1107aa37ec5bd18b5aa705fd8 /lib/tdb
parent6269cdcd1538e2e3cead9e0f3c156b0363d607a0 (diff)
downloadsamba-b37b452cb8c1f56b37b04abe7bffdede371ca361.tar.gz
samba-b37b452cb8c1f56b37b04abe7bffdede371ca361.tar.bz2
samba-b37b452cb8c1f56b37b04abe7bffdede371ca361.zip
tdb: fix recovery reuse after crash
If a process (or the machine) dies after just after writing the recovery head (pointing at the end of file), the recovery record will filled with 0x42. This will not invoke a recovery on open, since rec.magic != TDB_RECOVERY_MAGIC. Unfortunately, the first transaction commit will happily reuse that area: tdb_recovery_allocate() doesn't check the magic. The recovery record has length 0x42424242, and it writes that back into the now-valid-looking transaction header) for the next comer (which happens to be tdb_wipe_all in my tests). Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'lib/tdb')
-rw-r--r--lib/tdb/common/transaction.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/lib/tdb/common/transaction.c b/lib/tdb/common/transaction.c
index ed7e298a6e..67104eff7f 100644
--- a/lib/tdb/common/transaction.c
+++ b/lib/tdb/common/transaction.c
@@ -695,10 +695,16 @@ static int tdb_recovery_allocate(struct tdb_context *tdb,
rec.rec_len = 0;
- if (recovery_head != 0 &&
- methods->tdb_read(tdb, recovery_head, &rec, sizeof(rec), DOCONV()) == -1) {
- TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to read recovery record\n"));
- return -1;
+ if (recovery_head != 0) {
+ if (methods->tdb_read(tdb, recovery_head, &rec, sizeof(rec), DOCONV()) == -1) {
+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to read recovery record\n"));
+ return -1;
+ }
+ /* ignore invalid recovery regions: can happen in crash */
+ if (rec.magic != TDB_RECOVERY_MAGIC &&
+ rec.magic != TDB_RECOVERY_INVALID_MAGIC) {
+ recovery_head = 0;
+ }
}
*recovery_size = tdb_recovery_size(tdb);