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 <gb...@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 <gb...@sernet.de>
    Reviewed-by: Michael Adam <ob...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>
    
    Autobuild-User(master): Michael Adam <ob...@samba.org>
    Autobuild-Date(master): Tue Feb 19 13:56:57 CET 2013 on sn-devel-104

commit d8dd0ecc484ccc0c3450c3e96725e56e8bf1a9ef
Author: Gregor Beck <gb...@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 <gb...@sernet.de>
    Reviewed-by: Michael Adam <ob...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit d23f19ab00314d773edb07a45e754365db378668
Author: Gregor Beck <gb...@sernet.de>
Date:   Wed Dec 12 16:06:50 2012 +0100

    s3:smbXsrv_open: add smbXsrv_open_global_traverse()
    
    Signed-off-by: Gregor Beck <gb...@sernet.de>
    Reviewed-by: Michael Adam <ob...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit 60721a378240cb08e3f2ac0a1de14df5c9130010
Author: Gregor Beck <gb...@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 <gb...@sernet.de>
    Reviewed-by: Michael Adam <ob...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@samba.org>

commit 93e22bb1c401b423b0242e6923b8e7944f793b3f
Author: Gregor Beck <gb...@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 <gb...@sernet.de>
    Reviewed-by: Michael Adam <ob...@samba.org>
    Reviewed-by: Stefan Metzmacher <me...@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

Reply via email to