diff options
author | Andrew Tridgell <tridge@samba.org> | 2009-09-15 10:00:24 -0700 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2009-09-15 18:45:42 -0700 |
commit | 12f689eef4394e8c2cf8efdded06d5b398d6e0a7 (patch) | |
tree | c22532523c885e74042c46d596d5dcdf3bb7e6cf | |
parent | 00fb6705ffc937617e11c6da33b39bad7dda2ac3 (diff) | |
download | samba-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.
-rw-r--r-- | source4/lib/ldb/ldb_tdb/ldb_index.c | 11 | ||||
-rw-r--r-- | source4/lib/ldb/ldb_tdb/ldb_pack.c | 4 | ||||
-rw-r--r-- | source4/lib/ldb/ldb_tdb/ldb_search.c | 18 | ||||
-rw-r--r-- | source4/lib/ldb/ldb_tdb/ldb_tdb.h | 2 |
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); |