1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-20 22:50:26 +03:00

Revert "Fix bug #11394 - Crash: Bad talloc magic value - access after free"

This reverts commit 569ce95de57511d6082196ca4cc0938d78700351.

This has been committed by accident. Right patchset, but wrong authorship.
Patchset with correct authorship to follow.
This commit is contained in:
Karolin Seeger 2016-01-11 11:15:19 +01:00
parent 234861b0bf
commit c36c6e959b
2 changed files with 76 additions and 132 deletions

View File

@ -22,15 +22,11 @@
#include "dbwrap/dbwrap_private.h"
#include "dbwrap/dbwrap_rbt.h"
#include "../lib/util/rbtree.h"
#include "../lib/util/dlinklist.h"
#define DBWRAP_RBT_ALIGN(_size_) (((_size_)+15)&~15)
struct db_rbt_ctx {
struct rb_root tree;
struct db_rbt_node *nodes;
size_t traverse_read;
struct db_rbt_node **traverse_nextp;
};
struct db_rbt_rec {
@ -42,7 +38,6 @@ struct db_rbt_rec {
struct db_rbt_node {
struct rb_node rb_node;
size_t keysize, valuesize;
struct db_rbt_node *prev, *next;
};
/*
@ -126,16 +121,11 @@ static NTSTATUS db_rbt_store(struct db_record *rec, TDB_DATA data, int flag)
struct db_rbt_node *node;
struct rb_node ** p;
struct rb_node *parent = NULL;
struct db_rbt_node *parent_node = NULL;
struct rb_node * parent;
ssize_t reclen;
TDB_DATA this_key, this_val;
if (db_ctx->traverse_read > 0) {
return NT_STATUS_MEDIA_WRITE_PROTECTED;
}
if (rec_priv->node != NULL) {
/*
@ -163,25 +153,18 @@ static NTSTATUS db_rbt_store(struct db_record *rec, TDB_DATA data, int flag)
return NT_STATUS_INSUFFICIENT_RESOURCES;
}
node = talloc_zero_size(db_ctx, reclen);
node = talloc_size(db_ctx, reclen);
if (node == NULL) {
return NT_STATUS_NO_MEMORY;
}
if (rec_priv->node != NULL) {
if (db_ctx->traverse_nextp != NULL) {
if (*db_ctx->traverse_nextp == rec_priv->node) {
*db_ctx->traverse_nextp = node;
}
}
/*
* We need to delete the key from the tree and start fresh,
* there's not enough space in the existing record
*/
rb_erase(&rec_priv->node->rb_node, &db_ctx->tree);
DLIST_REMOVE(db_ctx->nodes, rec_priv->node);
/*
* Keep the existing node around for a while: If the record
@ -189,6 +172,8 @@ static NTSTATUS db_rbt_store(struct db_record *rec, TDB_DATA data, int flag)
*/
}
ZERO_STRUCT(node->rb_node);
node->keysize = rec->key.dsize;
node->valuesize = data.dsize;
@ -208,10 +193,9 @@ static NTSTATUS db_rbt_store(struct db_record *rec, TDB_DATA data, int flag)
TDB_DATA search_key, search_val;
int res;
r = db_rbt2node(*p);
parent = (*p);
parent_node = r;
r = db_rbt2node(*p);
db_rbt_parse_node(r, &search_key, &search_val);
@ -229,7 +213,6 @@ static NTSTATUS db_rbt_store(struct db_record *rec, TDB_DATA data, int flag)
}
rb_link_node(&node->rb_node, parent, p);
DLIST_ADD_AFTER(db_ctx->nodes, node, parent_node);
rb_insert_color(&node->rb_node, &db_ctx->tree);
return NT_STATUS_OK;
@ -241,27 +224,26 @@ static NTSTATUS db_rbt_delete(struct db_record *rec)
rec->db->private_data, struct db_rbt_ctx);
struct db_rbt_rec *rec_priv = (struct db_rbt_rec *)rec->private_data;
if (db_ctx->traverse_read > 0) {
return NT_STATUS_MEDIA_WRITE_PROTECTED;
}
if (rec_priv->node == NULL) {
return NT_STATUS_OK;
}
if (db_ctx->traverse_nextp != NULL) {
if (*db_ctx->traverse_nextp == rec_priv->node) {
*db_ctx->traverse_nextp = rec_priv->node->next;
}
}
rb_erase(&rec_priv->node->rb_node, &db_ctx->tree);
DLIST_REMOVE(db_ctx->nodes, rec_priv->node);
TALLOC_FREE(rec_priv->node);
return NT_STATUS_OK;
}
static NTSTATUS db_rbt_store_deny(struct db_record *rec, TDB_DATA data, int flag)
{
return NT_STATUS_MEDIA_WRITE_PROTECTED;
}
static NTSTATUS db_rbt_delete_deny(struct db_record *rec)
{
return NT_STATUS_MEDIA_WRITE_PROTECTED;
}
struct db_rbt_search_result {
TDB_DATA key;
TDB_DATA val;
@ -403,72 +385,61 @@ static NTSTATUS db_rbt_parse_record(struct db_context *db, TDB_DATA key,
}
static int db_rbt_traverse_internal(struct db_context *db,
struct rb_node *n,
int (*f)(struct db_record *db,
void *private_data),
void *private_data, uint32_t* count,
bool rw)
{
struct db_rbt_ctx *ctx = talloc_get_type_abort(
db->private_data, struct db_rbt_ctx);
struct db_rbt_node *cur = NULL;
struct db_rbt_node *next = NULL;
struct rb_node *rb_right;
struct rb_node *rb_left;
struct db_record rec;
struct db_rbt_rec rec_priv;
int ret;
for (cur = ctx->nodes; cur != NULL; cur = next) {
struct db_record rec;
struct db_rbt_rec rec_priv;
if (n == NULL) {
return 0;
}
rec_priv.node = cur;
next = rec_priv.node->next;
rb_left = n->rb_left;
rb_right = n->rb_right;
ZERO_STRUCT(rec);
rec.db = db;
rec.private_data = &rec_priv;
ret = db_rbt_traverse_internal(db, rb_left, f, private_data, count, rw);
if (ret != 0) {
return ret;
}
rec_priv.node = db_rbt2node(n);
/* n might be altered by the callback function */
n = NULL;
ZERO_STRUCT(rec);
rec.db = db;
rec.private_data = &rec_priv;
if (rw) {
rec.store = db_rbt_store;
rec.delete_rec = db_rbt_delete;
db_rbt_parse_node(rec_priv.node, &rec.key, &rec.value);
if (rw) {
ctx->traverse_nextp = &next;
}
ret = f(&rec, private_data);
(*count) ++;
if (rw) {
ctx->traverse_nextp = NULL;
}
if (ret != 0) {
return ret;
}
if (rec_priv.node != NULL) {
next = rec_priv.node->next;
}
} else {
rec.store = db_rbt_store_deny;
rec.delete_rec = db_rbt_delete_deny;
}
db_rbt_parse_node(rec_priv.node, &rec.key, &rec.value);
return 0;
}
static int db_rbt_traverse_read(struct db_context *db,
int (*f)(struct db_record *db,
void *private_data),
void *private_data)
{
struct db_rbt_ctx *ctx = talloc_get_type_abort(
db->private_data, struct db_rbt_ctx);
uint32_t count = 0;
int ret;
ctx->traverse_read++;
ret = db_rbt_traverse_internal(db,
f, private_data, &count,
false /* rw */);
ctx->traverse_read--;
ret = f(&rec, private_data);
(*count) ++;
if (ret != 0) {
return -1;
return ret;
}
if (count > INT_MAX) {
return -1;
if (rec_priv.node != NULL) {
/*
* If the current record is still there
* we should take the current rb_right.
*/
rb_right = rec_priv.node->rb_node.rb_right;
}
return count;
return db_rbt_traverse_internal(db, rb_right, f, private_data, count, rw);
}
static int db_rbt_traverse(struct db_context *db,
@ -479,19 +450,31 @@ static int db_rbt_traverse(struct db_context *db,
struct db_rbt_ctx *ctx = talloc_get_type_abort(
db->private_data, struct db_rbt_ctx);
uint32_t count = 0;
int ret;
if (ctx->traverse_nextp != NULL) {
int ret = db_rbt_traverse_internal(db, ctx->tree.rb_node,
f, private_data, &count,
true /* rw */);
if (ret != 0) {
return -1;
};
if (ctx->traverse_read > 0) {
return db_rbt_traverse_read(db, f, private_data);
}
if (count > INT_MAX) {
return -1;
}
return count;
}
ret = db_rbt_traverse_internal(db,
f, private_data, &count,
true /* rw */);
static int db_rbt_traverse_read(struct db_context *db,
int (*f)(struct db_record *db,
void *private_data),
void *private_data)
{
struct db_rbt_ctx *ctx = talloc_get_type_abort(
db->private_data, struct db_rbt_ctx);
uint32_t count = 0;
int ret = db_rbt_traverse_internal(db, ctx->tree.rb_node,
f, private_data, &count,
false /* rw */);
if (ret != 0) {
return -1;
}

View File

@ -8348,29 +8348,11 @@ static bool rbt_testval(struct db_context *db, const char *key,
return ret;
}
static int local_rbtree_traverse_read(struct db_record *rec, void *private_data)
{
int *count2 = (int *)private_data;
(*count2)++;
return 0;
}
static int local_rbtree_traverse_delete(struct db_record *rec, void *private_data)
{
int *count2 = (int *)private_data;
(*count2)++;
dbwrap_record_delete(rec);
return 0;
}
static bool run_local_rbtree(int dummy)
{
struct db_context *db;
bool ret = false;
int i;
NTSTATUS status;
int count = 0;
int count2 = 0;
db = db_open_rbt(NULL);
@ -8413,27 +8395,6 @@ static bool run_local_rbtree(int dummy)
}
ret = true;
count = 0; count2 = 0;
status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
&count2, &count);
printf("%s: read1: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
if ((count != count2) || (count != 1000)) {
ret = false;
}
count = 0; count2 = 0;
status = dbwrap_traverse(db, local_rbtree_traverse_delete,
&count2, &count);
printf("%s: delete: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
if ((count != count2) || (count != 1000)) {
ret = false;
}
count = 0; count2 = 0;
status = dbwrap_traverse_read(db, local_rbtree_traverse_read,
&count2, &count);
printf("%s: read2: %d %d, %s\n", __func__, count, count2, nt_errstr(status));
if ((count != count2) || (count != 0)) {
ret = false;
}
done:
TALLOC_FREE(db);