Prevent winbindd from segfaulting due to corrupted cache tdb.
authorAndreas Schneider <anschneider@suse.de>
Mon, 26 Nov 2007 10:44:30 +0000 (11:44 +0100)
committerMichael Adam <obnox@samba.org>
Mon, 7 Jan 2008 09:24:34 +0000 (10:24 +0100)
If we try to flush the caches and due to a corrupted tdb we and have no tdb
context close the tdb and validate it. Initialize the cache afterwards again.

source/winbindd/winbindd.c
source/winbindd/winbindd_cache.c

index 07cf22618e4a37b678876857363e176c103a4cb3..dfad50bf964ba9a33f6ef37a6378494c7bcd369c 100644 (file)
@@ -121,7 +121,23 @@ static void flush_caches(void)
            otherwise cached access denied errors due to restrict anonymous
            hang around until the sequence number changes. */
 
            otherwise cached access denied errors due to restrict anonymous
            hang around until the sequence number changes. */
 
-       wcache_invalidate_cache();
+       if (wcache_invalidate_cache() < 0) {
+               DEBUG(0, ("invalidating the cache failed; revalidate the cache\n"));
+               /* Close the cache to be able to valdite the cache */
+               close_winbindd_cache();
+               /*
+                * Ensure all cache and idmap caches are consistent
+                * before we initialize the cache again.
+                */
+               if (winbindd_validate_cache() < 0) {
+                       DEBUG(0, ("corrupted tdb found, trying to restore backup\n"));
+               }
+
+               /* Initialize cache again. */
+               if (!initialize_winbindd_cache()) {
+                       exit(1);
+               }
+       }
 }
 
 /* Handle the signal by unlinking socket and exiting */
 }
 
 /* Handle the signal by unlinking socket and exiting */
index f63c7a5b2f7185b9384fa9e3b9bcbdf81fd572a5..62a68aa8aafd38b497ca20b8512a29a25d2be3d4 100644 (file)
@@ -2261,7 +2261,7 @@ void wcache_invalidate_samlogon(struct winbindd_domain *domain,
        netsamlogon_clear_cached_user(cache->tdb, info3);
 }
 
        netsamlogon_clear_cached_user(cache->tdb, info3);
 }
 
-void wcache_invalidate_cache(void)
+int wcache_invalidate_cache(void)
 {
        struct winbindd_domain *domain;
 
 {
        struct winbindd_domain *domain;
 
@@ -2270,9 +2270,15 @@ void wcache_invalidate_cache(void)
 
                DEBUG(10, ("wcache_invalidate_cache: invalidating cache "
                           "entries for %s\n", domain->name));
 
                DEBUG(10, ("wcache_invalidate_cache: invalidating cache "
                           "entries for %s\n", domain->name));
-               if (cache)
-                       tdb_traverse(cache->tdb, traverse_fn, NULL);
+               if (cache) {
+                       if (cache->tdb) {
+                               tdb_traverse(cache->tdb, traverse_fn, NULL);
+                       } else {
+                               return -1;
+                       }
+               }
        }
        }
+       return 0;
 }
 
 bool init_wcache(void)
 }
 
 bool init_wcache(void)
@@ -2354,6 +2360,16 @@ bool initialize_winbindd_cache(void)
        return True;
 }
 
        return True;
 }
 
+void close_winbindd_cache()
+{
+       if (!wcache)
+               return;
+       if (wcache->tdb) {
+               tdb_close(wcache->tdb);
+               wcache->tdb = NULL;
+       }
+}
+
 void cache_store_response(pid_t pid, struct winbindd_response *response)
 {
        fstring key_str;
 void cache_store_response(pid_t pid, struct winbindd_response *response)
 {
        fstring key_str;