From: Ralph Boehme Date: Tue, 7 Oct 2025 16:39:33 +0000 (+0200) Subject: s3/librpc: open_files.idl: updates for Persistent Handles X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=22b3b321d64b6b2f4e6ca96b3e979c4ce3e0d3a1;p=thirdparty%2Fsamba.git s3/librpc: open_files.idl: updates for Persistent Handles New share_mode_entry flag: - SHARE_ENTRY_FLAG_PERSISTENT_OPEN New share_mode_data member: - num_persistent New share_mode_entry members: - create_guid - protect delete_token - open_persistent_id New vfs_default_durable_cookie members: - initial_delete_on_close The SHARE_ENTRY_FLAG_PERSISTENT_OPEN flag is crucially needed to modify the behaviour of share_entry_stale_pid() and used in other places when looking at a share_mode_entry and having to adust processing behaviour for Persistent Handles. num_persistent is used to track the number of Persistent Handles per share_mode_data record, adjusting dbwrap_store() behaviour depending on its value: if num_persistent is greater then zero, we pass DBWRAP_STORE_PERSISTENT. Without it we would have to iterate over oll share_mode_entry's every time we store the record. The create_guid ties together the open state from locking.tdb and the smbXsrv_open_global.tdb as an additional hardening to securely corolate both. The protect boolean is an in-memory flag indicating a disconnected Persistent Handle. We don't want to store this in the share_mode_entry on disk. open_persistent_id in the delete_token will be used to implement scavening delete_tokens when Persistent Handles with delete-on-close set expire. Windows will actually delete the file, but this is not easily possible with the current architecture of the scavenger, but we must at least correctly remove those stale tokens. initial_delete_on_close is used to preserve the fsp flag initial_delete_on_close across disconnects. When reconnecting the handle, the fsp flag can be reestablished based on the value from the cookie. Signed-off-by: Ralph Boehme Reviewed-by: Anoop C S --- diff --git a/source3/librpc/idl/open_files.idl b/source3/librpc/idl/open_files.idl index fe5012a9dba..53450ee06d2 100644 --- a/source3/librpc/idl/open_files.idl +++ b/source3/librpc/idl/open_files.idl @@ -17,7 +17,8 @@ interface open_files SHARE_ENTRY_FLAG_POSIX_OPEN = 0x0001, SHARE_ENTRY_FLAG_STREAM_BASEOPEN = 0x0002, SHARE_ENTRY_FLAG_DENY_DOS = 0x0004, - SHARE_ENTRY_FLAG_DENY_FCB = 0x0008 + SHARE_ENTRY_FLAG_DENY_FCB = 0x0008, + SHARE_ENTRY_FLAG_PERSISTENT_OPEN = 0x0010 } share_entry_flags; typedef [enum16bit] enum { @@ -34,6 +35,7 @@ interface open_files hyper op_mid; share_mode_entry_op_type op_type; GUID client_guid; + GUID create_guid; smb2_lease_key lease_key; uint32 access_mask; uint32 share_access; @@ -48,11 +50,17 @@ interface open_files * to store this share_mode_entry on disk. */ [skip] boolean8 stale; + /* + * In-memory flag indicating a disconnected Persistent Handle. + * We don't want to store this in the share_mode_entry on disk. + */ + [skip] boolean8 protect; } share_mode_entry; typedef [public] struct { uint32 name_hash; smb2_lease_key parent_lease_key; + hyper open_persistent_id; security_token *delete_nt_token; security_unix_token *delete_token; } delete_token; @@ -76,6 +84,7 @@ interface open_files [string,charset(UTF8)] char *servicepath; [string,charset(UTF8)] char *base_name; [string,charset(UTF8)] char *stream_name; + uint32 num_persistent; uint32 num_delete_tokens; [size_is(num_delete_tokens)] delete_token delete_tokens[]; [skip] boolean8 not_stored; @@ -130,6 +139,7 @@ interface open_files hyper initial_allocation_size; hyper position_information; boolean8 write_time_forced; + boolean8 initial_delete_on_close; vfs_default_durable_stat stat_info; } vfs_default_durable_cookie; diff --git a/source3/locking/locking.c b/source3/locking/locking.c index cebdb311b4b..2f78bae6285 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -772,6 +772,10 @@ static bool add_delete_on_close_token(struct share_mode_data *d, dtl->parent_lease_key = lease->parent_lease_key; } + if (fsp->op != NULL) { + dtl->open_persistent_id = fsp->op->global->open_persistent_id; + } + dtl->delete_nt_token = security_token_duplicate(d->delete_tokens, nt_tok); if (dtl->delete_nt_token == NULL) { return false; @@ -896,6 +900,11 @@ void set_delete_on_close_lck(files_struct *fsp, dt->parent_lease_key = lease->parent_lease_key; } + if (fsp->op != NULL) { + dt->open_persistent_id = + fsp->op->global->open_persistent_id; + } + TALLOC_FREE(dt->delete_nt_token); dt->delete_nt_token = security_token_duplicate(dt, nt_tok); SMB_ASSERT(dt->delete_nt_token != NULL); diff --git a/source3/locking/share_mode_lock.c b/source3/locking/share_mode_lock.c index 4f3a4b8201d..83a961ba01d 100644 --- a/source3/locking/share_mode_lock.c +++ b/source3/locking/share_mode_lock.c @@ -345,13 +345,13 @@ static struct share_mode_data *share_mode_memcache_fetch( } /* - * 124 is the sizeof an ndr-encoded struct share_mode_entry_buf. + * 140 is the sizeof an ndr-encoded struct share_mode_entry_buf. * Reading/writing entries will immediately error out if this * size differs (push/pull is done without allocs). */ struct share_mode_entry_buf { - uint8_t buf[124]; + uint8_t buf[140]; }; #define SHARE_MODE_ENTRY_SIZE (sizeof(struct share_mode_entry_buf))