[SCM] Samba Shared Repository - branch master updated
Michael Adam
obnox at samba.org
Tue Feb 19 05:57:02 MST 2013
The branch, master has been updated
via 5ab7725 s3:net: new implementation of "servid wipedbs" with smbXsrv_*
via d8dd0ec lib/util_tdb: factor out tdb_data_talloc_copy()
via d23f19a s3:smbXsrv_open: add smbXsrv_open_global_traverse()
via 60721a3 s3:smbXsrv_tcon: pass record in smbXsrv_tcon_global_traverse()
via 93e22bb s3:smbXsrv_session: pass record in smbXsrv_session_global_traverse()
from bdb80ae s3:smbd:smb2: fix segfault (access after free) in durable disconnect code
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 5ab77259746ef3811a64f6c7880ae2263d512c16
Author: Gregor Beck <gbeck at sernet.de>
Date: Thu Dec 13 13:00:28 2012 +0100
s3:net: new implementation of "servid wipedbs" with smbXsrv_*
Signed-off-by: Gregor Beck <gbeck at sernet.de>
Reviewed-by: Michael Adam <obnox at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
Autobuild-User(master): Michael Adam <obnox at samba.org>
Autobuild-Date(master): Tue Feb 19 13:56:57 CET 2013 on sn-devel-104
commit d8dd0ecc484ccc0c3450c3e96725e56e8bf1a9ef
Author: Gregor Beck <gbeck at sernet.de>
Date: Thu Jan 10 11:09:09 2013 +0100
lib/util_tdb: factor out tdb_data_talloc_copy()
Signed-off-by: Gregor Beck <gbeck at sernet.de>
Reviewed-by: Michael Adam <obnox at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
commit d23f19ab00314d773edb07a45e754365db378668
Author: Gregor Beck <gbeck at sernet.de>
Date: Wed Dec 12 16:06:50 2012 +0100
s3:smbXsrv_open: add smbXsrv_open_global_traverse()
Signed-off-by: Gregor Beck <gbeck at sernet.de>
Reviewed-by: Michael Adam <obnox at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
commit 60721a378240cb08e3f2ac0a1de14df5c9130010
Author: Gregor Beck <gbeck at sernet.de>
Date: Thu Dec 13 15:27:07 2012 +0100
s3:smbXsrv_tcon: pass record in smbXsrv_tcon_global_traverse()
Signed-off-by: Gregor Beck <gbeck at sernet.de>
Reviewed-by: Michael Adam <obnox at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
commit 93e22bb1c401b423b0242e6923b8e7944f793b3f
Author: Gregor Beck <gbeck at sernet.de>
Date: Thu Dec 13 15:26:49 2012 +0100
s3:smbXsrv_session: pass record in smbXsrv_session_global_traverse()
Signed-off-by: Gregor Beck <gbeck at sernet.de>
Reviewed-by: Michael Adam <obnox at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
-----------------------------------------------------------------------
Summary of changes:
lib/util/util_tdb.c | 15 +
lib/util/util_tdb.h | 1 +
source3/smbd/globals.h | 4 +
source3/smbd/smbXsrv_open.c | 73 +++++
source3/smbd/smbXsrv_session.c | 1 +
source3/smbd/smbXsrv_tcon.c | 1 +
source3/utils/net_idmap_check.c | 23 +--
source3/utils/net_serverid.c | 566 ++++++++++++++++++++++++++++++++++++++-
8 files changed, 663 insertions(+), 21 deletions(-)
Changeset truncated at 500 lines:
diff --git a/lib/util/util_tdb.c b/lib/util/util_tdb.c
index c005c82..93df958 100644
--- a/lib/util/util_tdb.c
+++ b/lib/util/util_tdb.c
@@ -63,6 +63,21 @@ TDB_DATA string_term_tdb_data(const char *string)
return make_tdb_data((const uint8_t *)string, string ? strlen(string) + 1 : 0);
}
+TDB_DATA tdb_data_talloc_copy(TALLOC_CTX* mem_ctx, TDB_DATA data) {
+ TDB_DATA ret = {
+ .dptr = (uint8_t *)talloc_size(mem_ctx, data.dsize+1),
+ .dsize = data.dsize
+ };
+ if (ret.dptr == NULL) {
+ ret.dsize = 0;
+ } else {
+ memcpy(ret.dptr, data.dptr, data.dsize);
+ ret.dptr[ret.dsize] = '\0';
+ }
+ return ret;
+}
+
+
/****************************************************************************
Lock a chain by string. Return non-zero if lock failed.
****************************************************************************/
diff --git a/lib/util/util_tdb.h b/lib/util/util_tdb.h
index d8a2333..630bdf6 100644
--- a/lib/util/util_tdb.h
+++ b/lib/util/util_tdb.h
@@ -30,6 +30,7 @@ bool tdb_data_equal(TDB_DATA t1, TDB_DATA t2);
bool tdb_data_is_empty(TDB_DATA d);
TDB_DATA string_tdb_data(const char *string);
TDB_DATA string_term_tdb_data(const char *string);
+TDB_DATA tdb_data_talloc_copy(TALLOC_CTX* mem_ctx, TDB_DATA data);
/****************************************************************************
Lock a chain by string. Return non-zero if lock failed.
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 6ead962..90e9ab4 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -457,6 +457,10 @@ NTSTATUS smb2srv_open_recreate(struct smbXsrv_connection *conn,
struct GUID create_guid,
NTTIME now,
struct smbXsrv_open **_open);
+struct smbXsrv_open_global0;
+NTSTATUS smbXsrv_open_global_traverse(
+ int (*fn)(struct smbXsrv_open_global0 *, void *),
+ void *private_data);
struct smbd_smb2_request {
struct smbd_smb2_request *prev, *next;
diff --git a/source3/smbd/smbXsrv_open.c b/source3/smbd/smbXsrv_open.c
index be39cbc..2c2798b 100644
--- a/source3/smbd/smbXsrv_open.c
+++ b/source3/smbd/smbXsrv_open.c
@@ -1277,3 +1277,76 @@ NTSTATUS smb2srv_open_recreate(struct smbXsrv_connection *conn,
*_open = op;
return NT_STATUS_OK;
}
+
+
+struct smbXsrv_open_global_traverse_state {
+ int (*fn)(struct smbXsrv_open_global0 *, void *);
+ void *private_data;
+};
+
+static int smbXsrv_open_global_traverse_fn(struct db_record *rec, void *data)
+{
+ int ret = -1;
+ struct smbXsrv_open_global_traverse_state *state =
+ (struct smbXsrv_open_global_traverse_state*)data;
+ TDB_DATA key = dbwrap_record_get_key(rec);
+ TDB_DATA val = dbwrap_record_get_value(rec);
+ DATA_BLOB blob = data_blob_const(val.dptr, val.dsize);
+ struct smbXsrv_open_globalB global_blob;
+ enum ndr_err_code ndr_err;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ ndr_err = ndr_pull_struct_blob(&blob, frame, &global_blob,
+ (ndr_pull_flags_fn_t)ndr_pull_smbXsrv_open_globalB);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ DEBUG(1,("Invalid record in smbXsrv_open_global.tdb:"
+ "key '%s' ndr_pull_struct_blob - %s\n",
+ hex_encode_talloc(frame, key.dptr, key.dsize),
+ ndr_errstr(ndr_err)));
+ goto done;
+ }
+
+ if (global_blob.version != SMBXSRV_VERSION_0) {
+ DEBUG(1,("Invalid record in smbXsrv_open_global.tdb:"
+ "key '%s' unsuported version - %d\n",
+ hex_encode_talloc(frame, key.dptr, key.dsize),
+ (int)global_blob.version));
+ goto done;
+ }
+
+ global_blob.info.info0->db_rec = rec;
+ ret = state->fn(global_blob.info.info0, state->private_data);
+done:
+ TALLOC_FREE(frame);
+ return ret;
+}
+
+NTSTATUS smbXsrv_open_global_traverse(
+ int (*fn)(struct smbXsrv_open_global0 *, void *),
+ void *private_data)
+{
+
+ NTSTATUS status;
+ int count = 0;
+ struct smbXsrv_open_global_traverse_state state = {
+ .fn = fn,
+ .private_data = private_data,
+ };
+
+ become_root();
+ status = smbXsrv_open_global_init();
+ if (!NT_STATUS_IS_OK(status)) {
+ unbecome_root();
+ DEBUG(0, ("Failed to initialize open_global: %s\n",
+ nt_errstr(status)));
+ return status;
+ }
+
+ status = dbwrap_traverse_read(smbXsrv_open_global_db_ctx,
+ smbXsrv_open_global_traverse_fn,
+ &state,
+ &count);
+ unbecome_root();
+
+ return status;
+}
diff --git a/source3/smbd/smbXsrv_session.c b/source3/smbd/smbXsrv_session.c
index f3072ee..017880c 100644
--- a/source3/smbd/smbXsrv_session.c
+++ b/source3/smbd/smbXsrv_session.c
@@ -1560,6 +1560,7 @@ static int smbXsrv_session_global_traverse_fn(struct db_record *rec, void *data)
goto done;
}
+ global_blob.info.info0->db_rec = rec;
ret = state->fn(global_blob.info.info0, state->private_data);
done:
TALLOC_FREE(frame);
diff --git a/source3/smbd/smbXsrv_tcon.c b/source3/smbd/smbXsrv_tcon.c
index 49da84d..b6e2058 100644
--- a/source3/smbd/smbXsrv_tcon.c
+++ b/source3/smbd/smbXsrv_tcon.c
@@ -1200,6 +1200,7 @@ static int smbXsrv_tcon_global_traverse_fn(struct db_record *rec, void *data)
goto done;
}
+ global_blob.info.info0->db_rec = rec;
ret = state->fn(global_blob.info.info0, state->private_data);
done:
TALLOC_FREE(frame);
diff --git a/source3/utils/net_idmap_check.c b/source3/utils/net_idmap_check.c
index 4174238..e75c890 100644
--- a/source3/utils/net_idmap_check.c
+++ b/source3/utils/net_idmap_check.c
@@ -42,7 +42,6 @@ static int traverse_check(struct db_record *rec, void* data);
/* TDB_DATA *******************************************************************/
static char* print_data(TALLOC_CTX* mem_ctx, TDB_DATA d);
static TDB_DATA parse_data(TALLOC_CTX* mem_ctx, const char** ptr);
-static TDB_DATA talloc_copy(TALLOC_CTX* mem_ctx, TDB_DATA data);
/* record *********************************************************************/
@@ -325,7 +324,7 @@ static int add_record(struct check_ctx* ctx, TDB_DATA key, TDB_DATA value)
diff = unpack_diff(recvalue);
talloc_free(diff.nval.dptr);
}
- diff.nval = talloc_copy(ctx->diff, value);
+ diff.nval = tdb_data_talloc_copy(ctx->diff, value);
DEBUG_DIFF(2, mem, "TDB DIFF", key, diff.oval, diff.nval);
@@ -355,7 +354,7 @@ fetch_record(struct check_ctx* ctx, TALLOC_CTX* mem_ctx, TDB_DATA key)
if (NT_STATUS_IS_OK(status)) {
TDB_DATA_diff diff = unpack_diff(tmp);
- TDB_DATA ret = talloc_copy(mem_ctx, diff.nval);
+ TDB_DATA ret = tdb_data_talloc_copy(mem_ctx, diff.nval);
talloc_free(tmp.dptr);
return ret;
}
@@ -548,20 +547,6 @@ void adjust_hwm(struct check_ctx* ctx, const struct record* r) {
}
}
-TDB_DATA talloc_copy(TALLOC_CTX* mem_ctx, TDB_DATA data) {
- TDB_DATA ret = {
- .dptr = (uint8_t *)talloc_size(mem_ctx, data.dsize+1),
- .dsize = data.dsize
- };
- if (ret.dptr == NULL) {
- ret.dsize = 0;
- } else {
- memcpy(ret.dptr, data.dptr, data.dsize);
- ret.dptr[ret.dsize] = '\0';
- }
- return ret;
-}
-
static bool is_cstr(TDB_DATA str) {
return !tdb_data_is_empty(str) && str.dptr[str.dsize-1] == '\0';
}
@@ -603,8 +588,8 @@ parse_record(TALLOC_CTX* mem_ctx, TDB_DATA key, TDB_DATA val)
DEBUG(0, ("Out of memory.\n"));
return NULL;
}
- ret->key = talloc_copy(ret, key);
- ret->val = talloc_copy(ret, val);
+ ret->key = tdb_data_talloc_copy(ret, key);
+ ret->val = tdb_data_talloc_copy(ret, val);
if ((ret->key.dptr == NULL && key.dptr != NULL) ||
(ret->val.dptr == NULL && val.dptr != NULL))
{
diff --git a/source3/utils/net_serverid.c b/source3/utils/net_serverid.c
index 2d25ba7..90448c1 100644
--- a/source3/utils/net_serverid.c
+++ b/source3/utils/net_serverid.c
@@ -20,9 +20,12 @@
#include "includes.h"
#include "utils/net.h"
#include "dbwrap/dbwrap.h"
+#include "dbwrap/dbwrap_rbt.h"
#include "serverid.h"
#include "session.h"
#include "lib/conn_tdb.h"
+#include "smbd/globals.h"
+#include "util_tdb.h"
static int net_serverid_list_fn(const struct server_id *id,
uint32_t msg_flags, void *priv)
@@ -66,11 +69,570 @@ static int net_serverid_wipe(struct net_context *c, int argc,
return serverid_traverse(net_serverid_wipe_fn, NULL) ? 0 : -1;
}
+
+struct wipedbs_record_marker {
+ struct wipedbs_record_marker *prev, *next;
+ TDB_DATA key, val;
+ const char *desc;
+};
+
+struct wipedbs_server_data {
+ struct server_id server_id;
+ const char *server_id_str;
+ bool exists;
+ struct wipedbs_record_marker *session_records;
+ struct wipedbs_record_marker *tcon_records;
+ struct wipedbs_record_marker *open_records;
+};
+
+struct wipedbs_state {
+ struct db_context *id2server_data;
+ struct {
+ struct {
+ int total;
+ int existing;
+ int disconnected;
+ } server;
+ struct {
+ int total;
+ int disconnected;
+ int todelete;
+ int failure;
+ } session, tcon, open;
+ int open_timed_out;
+ } stat;
+ struct server_id *server_ids;
+ bool *server_exists;
+ int idx;
+ struct db_context *session_db;
+ struct db_context *tcon_db;
+ struct db_context *open_db;
+ struct timeval now;
+ bool testmode;
+ bool verbose;
+};
+
+static struct wipedbs_server_data *get_server_data(struct wipedbs_state *state,
+ const struct server_id *id)
+{
+ struct wipedbs_server_data *ret = NULL;
+ TDB_DATA key, val = tdb_null;
+ NTSTATUS status;
+
+ key = make_tdb_data((const void*)&id->unique_id, sizeof(id->unique_id));
+ status = dbwrap_fetch(state->id2server_data, talloc_tos(), key, &val);
+ if (NT_STATUS_IS_OK(status)) {
+ ret = *(struct wipedbs_server_data**) val.dptr;
+ TALLOC_FREE(val.dptr);
+ } else if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
+ ret = talloc_zero(state->id2server_data,
+ struct wipedbs_server_data);
+ if (ret == NULL) {
+ DEBUG(0, ("Failed to allocate server entry for %s\n",
+ server_id_str(talloc_tos(), id)));
+ goto done;
+ }
+ ret->server_id = *id;
+ ret->server_id_str = server_id_str(ret, id);
+ ret->exists = true;
+ val = make_tdb_data((const void*)&ret, sizeof(ret));
+ status = dbwrap_store(state->id2server_data,
+ key, val, TDB_INSERT);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("Failed to store server entry for %s: %s\n",
+ server_id_str(talloc_tos(), id),
+ nt_errstr(status)));
+ }
+ goto done;
+ } else {
+ DEBUG(0, ("Failed to fetch server entry for %s: %s\n",
+ server_id_str(talloc_tos(), id), nt_errstr(status)));
+ goto done;
+ }
+ if (!server_id_equal(id, &ret->server_id)) {
+ DEBUG(0, ("uniq id collision for %s and %s\n",
+ server_id_str(talloc_tos(), id),
+ server_id_str(talloc_tos(), &ret->server_id)));
+ smb_panic("server_id->unique_id not unique!");
+ }
+done:
+ return ret;
+}
+
+static int wipedbs_traverse_sessions(struct smbXsrv_session_global0 *session,
+ void *wipedbs_state)
+{
+ struct wipedbs_state *state =
+ talloc_get_type_abort(wipedbs_state,
+ struct wipedbs_state);
+ struct wipedbs_server_data *sd;
+ struct wipedbs_record_marker *rec;
+ TDB_DATA tmp;
+ int ret = -1;
+
+ assert(session->num_channels == 1);
+
+ state->stat.session.total++;
+
+ sd = get_server_data(state, &session->channels[0].server_id);
+ if (sd == NULL) {
+ goto done;
+ }
+
+ if (server_id_is_disconnected(&sd->server_id)) {
+ state->stat.session.disconnected++;
+ }
+
+ rec = talloc_zero(sd, struct wipedbs_record_marker);
+ if (rec == NULL) {
+ DEBUG(0, ("Out of memory!\n"));
+ goto done;
+ }
+
+ tmp = dbwrap_record_get_key(session->db_rec);
+ rec->key = tdb_data_talloc_copy(rec, tmp);
+ tmp = dbwrap_record_get_value(session->db_rec);
+ rec->val = tdb_data_talloc_copy(rec, tmp);
+
+ rec->desc = talloc_asprintf(
+ rec, "session[global: %u wire: %lu]",
+ session->session_global_id, session->session_wire_id);
+
+ if ((rec->key.dptr == NULL) || (rec->val.dptr == NULL) ||
+ (rec->desc == NULL))
+ {
+ DEBUG(0, ("Out of memory!\n"));
+ goto done;
+ }
+
+ state->session_db = dbwrap_record_get_db(session->db_rec);
+
+ DLIST_ADD(sd->session_records, rec);
+ ret = 0;
+done:
+ return ret;
+}
+
+static int wipedbs_traverse_tcon(struct smbXsrv_tcon_global0 *tcon,
+ void *wipedbs_state)
+{
+ struct wipedbs_state *state =
+ talloc_get_type_abort(wipedbs_state,
+ struct wipedbs_state);
+ struct wipedbs_server_data *sd;
+ struct wipedbs_record_marker *rec;
+ TDB_DATA tmp;
+ int ret = -1;
+
+ state->stat.tcon.total++;
+
+ sd = get_server_data(state, &tcon->server_id);
+ if (sd == NULL) {
+ goto done;
+ }
+
+ if (server_id_is_disconnected(&sd->server_id)) {
+ state->stat.tcon.disconnected++;
+ }
+
+ rec = talloc_zero(sd, struct wipedbs_record_marker);
+ if (rec == NULL) {
+ DEBUG(0, ("Out of memory!\n"));
+ goto done;
+ }
+
+ tmp = dbwrap_record_get_key(tcon->db_rec);
+ rec->key = tdb_data_talloc_copy(rec, tmp);
+ tmp = dbwrap_record_get_value(tcon->db_rec);
+ rec->val = tdb_data_talloc_copy(rec, tmp);
+
+ rec->desc = talloc_asprintf(
+ rec, "tcon[global: %u wire: %u session: %u share: %s]",
+ tcon->tcon_global_id, tcon->tcon_wire_id,
+ tcon->session_global_id, tcon->share_name);
+
+ if ((rec->key.dptr == NULL) || (rec->val.dptr == NULL) ||
+ (rec->desc == NULL))
+ {
+ DEBUG(0, ("Out of memory!\n"));
+ goto done;
+ }
+
+ state->tcon_db = dbwrap_record_get_db(tcon->db_rec);
+
+ DLIST_ADD(sd->tcon_records, rec);
+ ret = 0;
+
+done:
+ return ret;
+}
+
+static int wipedbs_traverse_open(struct smbXsrv_open_global0 *open,
+ void *wipedbs_state)
+{
+ struct wipedbs_state *state =
+ talloc_get_type_abort(wipedbs_state,
+ struct wipedbs_state);
+ struct wipedbs_server_data *sd;
+ struct wipedbs_record_marker *rec;
+ TDB_DATA tmp;
+ int ret = -1;
+
+ state->stat.open.total++;
+
+ sd = get_server_data(state, &open->server_id);
+ if (sd == NULL) {
+ goto done;
+ }
+
+ if (server_id_is_disconnected(&sd->server_id)) {
+ struct timeval disconnect_time;
+ int64_t tdiff;
+ bool reached;
+
+ state->stat.open.disconnected++;
+
+ nttime_to_timeval(&disconnect_time, open->disconnect_time);
+ tdiff = usec_time_diff(&state->now, &disconnect_time);
+ reached = (tdiff >= 1000*open->durable_timeout_msec);
+
+ if (state->verbose) {
+ TALLOC_CTX *mem_ctx = talloc_new(talloc_tos());
+ d_printf("open[global: %u] disconnected at "
+ "[%s] %us ago with timeout of %us "
+ "-%s reached\n",
+ open->open_global_id,
+ nt_time_string(mem_ctx, open->disconnect_time),
+ (unsigned)(tdiff/1000000),
+ open->durable_timeout_msec / 1000,
+ reached ? "" : " not");
+ talloc_free(mem_ctx);
+ }
+
+ if (!reached) {
+ ret = 0;
+ goto done;
+ }
+ state->stat.open_timed_out++;
+ }
+
+ rec = talloc_zero(sd, struct wipedbs_record_marker);
+ if (rec == NULL) {
+ DEBUG(0, ("Out of memory!\n"));
+ goto done;
+ }
+
+ tmp = dbwrap_record_get_key(open->db_rec);
+ rec->key = tdb_data_talloc_copy(rec, tmp);
+ tmp = dbwrap_record_get_value(open->db_rec);
+ rec->val = tdb_data_talloc_copy(rec, tmp);
+
+ rec->desc = talloc_asprintf(
--
Samba Shared Repository
More information about the samba-cvs
mailing list