From 2d9bb67d25181eba79b95df661e5a5d613b4a850 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 23 Aug 2019 14:30:07 +0200 Subject: [PATCH] smbd: Use share_mode_forall_entries() in vfs_default_durable_reconnect() The durable reconnect mainly has to check that there is one and only one entry, and it has to reset it with the new values. Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- source3/smbd/durable.c | 78 +++++++++++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 28 deletions(-) diff --git a/source3/smbd/durable.c b/source3/smbd/durable.c index c1e0c869822..c71a948191a 100644 --- a/source3/smbd/durable.c +++ b/source3/smbd/durable.c @@ -496,6 +496,22 @@ static bool vfs_default_durable_reconnect_check_stat( return true; } +static bool durable_reconnect_fn( + struct share_mode_entry *e, + bool *modified, + void *private_data) +{ + struct share_mode_entry *dst_e = private_data; + + if (dst_e->pid.pid != 0) { + DBG_INFO("Found more than one entry, invalidating previous\n"); + dst_e->pid.pid = 0; + return true; /* end the loop through share mode entries */ + } + *dst_e = *e; + return false; /* Look at potential other entries */ +} + NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn, struct smb_request *smb1req, struct smbXsrv_open *op, @@ -505,7 +521,7 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn, DATA_BLOB *new_cookie) { struct share_mode_lock *lck; - struct share_mode_entry *e; + struct share_mode_entry e; struct files_struct *fsp = NULL; NTSTATUS status; bool ok; @@ -596,27 +612,22 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn, return NT_STATUS_OBJECT_NAME_NOT_FOUND; } - if (lck->data->num_share_modes == 0) { - DEBUG(1, ("vfs_default_durable_reconnect: Error: no share-mode " - "entry in existing share mode lock\n")); + e = (struct share_mode_entry) { .pid.pid = 0 }; + + ok = share_mode_forall_entries(lck, durable_reconnect_fn, &e); + if (!ok) { + DBG_WARNING("share_mode_forall_entries failed\n"); TALLOC_FREE(lck); return NT_STATUS_INTERNAL_DB_ERROR; } - if (lck->data->num_share_modes > 1) { - /* - * It can't be durable if there is more than one handle - * on the file. - */ - DEBUG(5, ("vfs_default_durable_reconnect: more than one " - "share-mode entry - can not be durable\n")); + if (e.pid.pid == 0) { + DBG_WARNING("Did not find a unique valid share mode entry\n"); TALLOC_FREE(lck); return NT_STATUS_OBJECT_NAME_NOT_FOUND; } - e = &lck->data->share_modes[0]; - - if (!server_id_is_disconnected(&e->pid)) { + if (!server_id_is_disconnected(&e.pid)) { DEBUG(5, ("vfs_default_durable_reconnect: denying durable " "reconnect for handle that was not marked " "disconnected (e.g. smbd or cluster node died)\n")); @@ -624,17 +635,17 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn, return NT_STATUS_OBJECT_NAME_NOT_FOUND; } - if (e->share_file_id != op->global->open_persistent_id) { + if (e.share_file_id != op->global->open_persistent_id) { DBG_INFO("denying durable " "share_file_id changed %"PRIu64" != %"PRIu64" " "(e.g. another client had opened the file)\n", - e->share_file_id, + e.share_file_id, op->global->open_persistent_id); TALLOC_FREE(lck); return NT_STATUS_OBJECT_NAME_NOT_FOUND; } - if ((e->access_mask & (FILE_WRITE_DATA|FILE_APPEND_DATA)) && + if ((e.access_mask & (FILE_WRITE_DATA|FILE_APPEND_DATA)) && !CAN_WRITE(conn)) { DEBUG(5, ("vfs_default_durable_reconnect: denying durable " @@ -656,12 +667,12 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn, return status; } - fsp->fh->private_options = e->private_options; + fsp->fh->private_options = e.private_options; fsp->file_id = file_id; fsp->file_pid = smb1req->smbpid; fsp->vuid = smb1req->vuid; - fsp->open_time = e->time; - fsp->access_mask = e->access_mask; + fsp->open_time = e.time; + fsp->access_mask = e.access_mask; fsp->can_read = ((fsp->access_mask & (FILE_READ_DATA)) != 0); fsp->can_write = ((fsp->access_mask & (FILE_WRITE_DATA|FILE_APPEND_DATA)) != 0); fsp->fnum = op->local_id; @@ -684,7 +695,7 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn, * We do not support aio write behind for smb2 */ fsp->aio_write_behind = false; - fsp->oplock_type = e->op_type; + fsp->oplock_type = e.op_type; if (fsp->oplock_type == LEASE_OPLOCK) { uint32_t current_state; @@ -695,15 +706,15 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn, * stored one in the share_mode_entry. */ if (!GUID_equal(fsp_client_guid(fsp), - &e->client_guid)) { + &e.client_guid)) { TALLOC_FREE(lck); fsp_free(fsp); return NT_STATUS_OBJECT_NAME_NOT_FOUND; } status = leases_db_get( - &e->client_guid, - &e->lease_key, + &e.client_guid, + &e.lease_key, &file_id, ¤t_state, /* current_state */ NULL, /* breaking */ @@ -719,7 +730,7 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn, fsp->lease = find_fsp_lease( fsp, - &e->lease_key, + &e.lease_key, current_state, lease_version, epoch); @@ -750,9 +761,20 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn, op->compat = fsp; fsp->op = op; - e->pid = messaging_server_id(conn->sconn->msg_ctx); - e->op_mid = smb1req->mid; - e->share_file_id = fsp->fh->gen_id; + ok = reset_share_mode_entry( + lck, + e.pid, + e.share_file_id, + messaging_server_id(conn->sconn->msg_ctx), + smb1req->mid, + fsp->fh->gen_id); + if (!ok) { + DBG_DEBUG("Could not set new share_mode_entry values\n"); + TALLOC_FREE(lck); + op->compat = NULL; + fsp_free(fsp); + return NT_STATUS_INTERNAL_ERROR; + } ok = brl_reconnect_disconnected(fsp); if (!ok) { -- 2.47.3