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:
parent
6a9c89b3ae
commit
4861194f39
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user