1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-27 03:21:53 +03:00

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.
This commit is contained in:
Andrew Tridgell 2009-09-15 10:00:24 -07:00
parent 6a9c89b3ae
commit 4861194f39
4 changed files with 30 additions and 5 deletions

View File

@ -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;
}

View File

@ -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) {

View File

@ -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");

View File

@ -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);