summaryrefslogtreecommitdiff
path: root/source4/lib
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2009-09-15 10:00:24 -0700
committerAndrew Tridgell <tridge@samba.org>2009-09-15 18:45:42 -0700
commit12f689eef4394e8c2cf8efdded06d5b398d6e0a7 (patch)
treec22532523c885e74042c46d596d5dcdf3bb7e6cf /source4/lib
parent00fb6705ffc937617e11c6da33b39bad7dda2ac3 (diff)
downloadsamba-12f689eef4394e8c2cf8efdded06d5b398d6e0a7.tar.gz
samba-12f689eef4394e8c2cf8efdded06d5b398d6e0a7.tar.bz2
samba-12f689eef4394e8c2cf8efdded06d5b398d6e0a7.zip
s4-ldb: cope better with corruption of tdb records
When doing an indexed search if we hit a corrupt record we abandoned the indexed search and did a full search. The problem was that we might have sent some records to the caller already, which means the caller ended up with duplicate records. Fix this by returning a search error if indexing returns an error and we have given any records to the caller.
Diffstat (limited to 'source4/lib')
-rw-r--r--source4/lib/ldb/ldb_tdb/ldb_index.c11
-rw-r--r--source4/lib/ldb/ldb_tdb/ldb_pack.c4
-rw-r--r--source4/lib/ldb/ldb_tdb/ldb_search.c18
-rw-r--r--source4/lib/ldb/ldb_tdb/ldb_tdb.h2
4 files changed, 30 insertions, 5 deletions
diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c
index 85fbfa0458..b959471d16 100644
--- a/source4/lib/ldb/ldb_tdb/ldb_index.c
+++ b/source4/lib/ldb/ldb_tdb/ldb_index.c
@@ -1037,7 +1037,8 @@ static int ltdb_index_dn(struct ldb_module *module,
extracting just the given attributes
*/
static int ltdb_index_filter(const struct dn_list *dn_list,
- struct ltdb_context *ac)
+ struct ltdb_context *ac,
+ uint32_t *match_count)
{
struct ldb_context *ldb;
struct ldb_message *msg;
@@ -1093,6 +1094,8 @@ static int ltdb_index_filter(const struct dn_list *dn_list,
ac->request_terminated = true;
return ret;
}
+
+ (*match_count)++;
}
return LDB_SUCCESS;
@@ -1103,7 +1106,7 @@ static int ltdb_index_filter(const struct dn_list *dn_list,
returns -1 if an indexed search is not possible, in which
case the caller should call ltdb_search_full()
*/
-int ltdb_search_indexed(struct ltdb_context *ac)
+int ltdb_search_indexed(struct ltdb_context *ac, uint32_t *match_count)
{
struct ldb_context *ldb;
void *data = ldb_module_get_private(ac->module);
@@ -1166,7 +1169,7 @@ int ltdb_search_indexed(struct ltdb_context *ac)
if (ret == LDB_SUCCESS) {
/* we've got a candidate list - now filter by the full tree
and extract the needed attributes */
- ret = ltdb_index_filter(dn_list, ac);
+ ret = ltdb_index_filter(dn_list, ac, match_count);
}
talloc_free(dn_list);
@@ -1578,6 +1581,8 @@ static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *
ret = ltdb_unpack_data(module, &data, msg);
if (ret != 0) {
+ ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid data for index %s\n",
+ ldb_dn_get_linearized(msg->dn));
talloc_free(msg);
return -1;
}
diff --git a/source4/lib/ldb/ldb_tdb/ldb_pack.c b/source4/lib/ldb/ldb_tdb/ldb_pack.c
index 5640e7053c..e7aeb47e72 100644
--- a/source4/lib/ldb/ldb_tdb/ldb_pack.c
+++ b/source4/lib/ldb/ldb_tdb/ldb_pack.c
@@ -236,6 +236,10 @@ int ltdb_unpack_data(struct ldb_module *module,
errno = EIO;
goto failed;
}
+ if (len == 0) {
+ errno = EIO;
+ goto failed;
+ }
message->elements[i].flags = 0;
message->elements[i].name = talloc_strndup(message->elements, (char *)p, len);
if (message->elements[i].name == NULL) {
diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c
index b307c5fb2f..a6647ccd50 100644
--- a/source4/lib/ldb/ldb_tdb/ldb_search.c
+++ b/source4/lib/ldb/ldb_tdb/ldb_search.c
@@ -265,6 +265,9 @@ int ltdb_search_dn1(struct ldb_module *module, struct ldb_dn *dn, struct ldb_mes
ret = ltdb_unpack_data(module, &tdb_data, msg);
free(tdb_data.dptr);
if (ret == -1) {
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+ ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid data for index %s\n",
+ ldb_dn_get_linearized(msg->dn));
return LDB_ERR_OPERATIONS_ERROR;
}
@@ -535,7 +538,9 @@ int ltdb_search(struct ltdb_context *ctx)
ctx->attrs = req->op.search.attrs;
if (ret == LDB_SUCCESS) {
- ret = ltdb_search_indexed(ctx);
+ uint32_t match_count = 0;
+
+ ret = ltdb_search_indexed(ctx, &match_count);
if (ret == LDB_ERR_NO_SUCH_OBJECT) {
/* Not in the index, therefore OK! */
ret = LDB_SUCCESS;
@@ -553,6 +558,17 @@ int ltdb_search(struct ltdb_context *ctx)
printf("FULL SEARCH: %s\n", expression);
talloc_free(expression);
#endif
+ if (match_count != 0) {
+ /* the indexing code gave an error
+ * after having returned at least one
+ * entry. This means the indexes are
+ * corrupt or a database record is
+ * corrupt. We cannot continue with a
+ * full search or we may return
+ * duplicate entries
+ */
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
ret = ltdb_search_full(ctx);
if (ret != LDB_SUCCESS) {
ldb_set_errstring(ldb, "Indexed and full searches both failed!\n");
diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h
index 75034dcf4b..c8c1dad5de 100644
--- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h
+++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h
@@ -82,7 +82,7 @@ int ltdb_check_at_attributes_values(const struct ldb_val *value);
struct ldb_parse_tree;
-int ltdb_search_indexed(struct ltdb_context *ctx);
+int ltdb_search_indexed(struct ltdb_context *ctx, uint32_t *);
int ltdb_index_add(struct ldb_module *module, const struct ldb_message *msg);
int ltdb_index_del(struct ldb_module *module, const struct ldb_message *msg);
int ltdb_index_one(struct ldb_module *module, const struct ldb_message *msg, int add);