s3:smbd: check for stale pid in delay_for_oplock_fn() when leases_db_get() fails
authorStefan Metzmacher <metze@samba.org>
Mon, 6 Jul 2020 06:58:22 +0000 (08:58 +0200)
committerKarolin Seeger <kseeger@samba.org>
Thu, 6 Aug 2020 12:18:21 +0000 (12:18 +0000)
If leases_db_get() failed the leases_db record might have been cleaned up for
stale processes. Check if the share-mode-entry owner is stale in this case and
return ignore the entry. In any other case, log a debug messages and panic.

Commit 05d4466a6d1ad048fa86aea09ec0a56a7b961369
"smbd: check for stale pid in get_lease_type()" fixed only one half of
this.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14428

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Tue Jul  7 02:47:46 UTC 2020 on sn-devel-184

(backported from commit 58adf349edfd3001ad071cc7ed8cfc551f67f8a2)
[metze@samba.org: use share_mode_stale_pid() instead of share_entry_stale_pid()]
[metze@samba.org: use file_id_string_tos() instead of file_id_str_buf()]

source3/smbd/open.c

index 888e6ad3af7d837beee3ef5fc5b7c030dbe89853..ac60c75c1397378a7956cdfee3fd9ea2910766bf 100644 (file)
@@ -1900,7 +1900,39 @@ static bool delay_for_oplock(files_struct *fsp,
                                NULL, /* breaking_to_required */
                                NULL, /* lease_version */
                                NULL); /* epoch */
-                       SMB_ASSERT(NT_STATUS_IS_OK(status));
+                       /*
+                        * leases_db_get() can return NT_STATUS_NOT_FOUND
+                        * if the share_mode_entry e is stale and the
+                        * lease record was already removed. In this case return
+                        * false so the traverse continues.
+                        */
+
+                       if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND) &&
+                           share_mode_stale_pid(d, i))
+                       {
+                               struct GUID_txt_buf guid_strbuf;
+                               DBG_DEBUG("leases_db_get for client_guid [%s] "
+                                         "lease_key [%"PRIu64"/%"PRIu64"] "
+                                         "file_id [%s] failed for stale "
+                                         "share_mode_entry\n",
+                                         GUID_buf_string(&e->client_guid, &guid_strbuf),
+                                         e->lease_key.data[0],
+                                         e->lease_key.data[1],
+                                         file_id_string_tos(&fsp->file_id));
+                               continue;
+                       }
+                       if (!NT_STATUS_IS_OK(status)) {
+                               struct GUID_txt_buf guid_strbuf;
+                               DBG_ERR("leases_db_get for client_guid [%s] "
+                                       "lease_key [%"PRIu64"/%"PRIu64"] "
+                                       "file_id [%s] failed: %s\n",
+                                       GUID_buf_string(&e->client_guid, &guid_strbuf),
+                                       e->lease_key.data[0],
+                                       e->lease_key.data[1],
+                                       file_id_string_tos(&fsp->file_id),
+                                       nt_errstr(status));
+                               smb_panic("leases_db_get() failed");
+                       }
                }
 
                break_to = e_lease_type & ~delay_mask;