]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
smbd: Use share_mode_forall_entries() in open_mode_check()
authorVolker Lendecke <vl@samba.org>
Fri, 16 Aug 2019 11:08:23 +0000 (13:08 +0200)
committerJeremy Allison <jra@samba.org>
Tue, 17 Sep 2019 22:49:37 +0000 (22:49 +0000)
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/smbd/open.c

index aee7ad2731a0fef9f5d28cc6afabeaa304d0f0fa..7cfcf85db07470d8beae06f75942461aeef34772 100644 (file)
@@ -1656,13 +1656,51 @@ static bool has_delete_on_close(struct share_mode_lock *lck,
  Returns -1 on error, or number of share modes on success (may be zero).
 ****************************************************************************/
 
+struct open_mode_check_state {
+       uint32_t access_mask;
+       uint32_t share_access;
+       bool conflict;
+};
+
+static bool open_mode_check_fn(
+       struct share_mode_entry *e,
+       bool *modified,
+       void *private_data)
+{
+       struct open_mode_check_state *state = private_data;
+       bool disconnected, conflict, stale;
+
+       disconnected = server_id_is_disconnected(&e->pid);
+       if (disconnected) {
+               return false;
+       }
+
+       conflict = share_conflict(
+               e->access_mask,
+               e->share_access,
+               state->access_mask,
+               state->share_access);
+       if (!conflict) {
+               return false;
+       }
+       stale = share_entry_stale_pid(e);
+       if (stale) {
+               return false;
+       }
+
+       state->conflict = true;
+       return true;
+}
+
 static NTSTATUS open_mode_check(connection_struct *conn,
                                struct share_mode_lock *lck,
                                uint32_t access_mask,
                                uint32_t share_access)
 {
-       struct share_mode_data *d = lck->data;
-       uint32_t i;
+       struct open_mode_check_state state = {
+               .access_mask = access_mask, .share_access = share_access,
+       };
+       bool ok;
 
        if (is_stat_open(access_mask)) {
                /* Stat open that doesn't trigger oplock breaks or share mode
@@ -1681,40 +1719,19 @@ static NTSTATUS open_mode_check(connection_struct *conn,
                        .fid = lck->data->id,
                        .self = messaging_server_id(conn->sconn->msg_ctx),
                };
-               bool ok;
-
                ok = share_mode_forall_entries(
                        lck, validate_my_share_entries_fn, &validate_state);
                SMB_ASSERT(ok);
        }
 #endif
 
-       for(i = 0; i < d->num_share_modes; i++) {
-               struct share_mode_entry *e = &d->share_modes[i];
-               bool conflict;
-
-               if (!is_valid_share_mode_entry(e)) {
-                       continue;
-               }
-               if (server_id_is_disconnected(&e->pid)) {
-                       continue;
-               }
-
-               /* someone else has a share lock on it, check to see if we can
-
-                * too */
-               conflict = share_conflict(
-                       e->access_mask,
-                       e->share_access,
-                       access_mask,
-                       share_access);
-               if (conflict) {
-                       if (share_mode_stale_pid(d, i)) {
-                               continue;
-                       }
-
-                       return NT_STATUS_SHARING_VIOLATION;
-               }
+       ok = share_mode_forall_entries(lck, open_mode_check_fn, &state);
+       if (!ok) {
+               DBG_DEBUG("share_mode_forall_entries failed\n");
+               return NT_STATUS_INTERNAL_ERROR;
+       }
+       if (state.conflict) {
+               return NT_STATUS_SHARING_VIOLATION;
        }
 
        return NT_STATUS_OK;