You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This commit was created on GitHub.com and signed with GitHub’s verified signature.
Added
publish_on_close hardening: CHANGE_NOTIFY event mapping. When
publish_on_close is enabled on a share, the CHANGE_NOTIFY watcher now
maps inotify events on hidden temp files (.rssmb-tmp.*) to events on
the client-visible final name, so no temp name ever surfaces to SMB
clients:
temp ADDED → FILE_ACTION_ADDED <final_name>
temp MODIFIED → FILE_ACTION_MODIFIED <final_name>
temp REMOVED → suppress (abort, delete-on-close, or publish rename)
Also confirmed via unit tests that (a) a durable handle's close
publishes its pending temp, (b) the startup orphan sweep runs on
share mount (not only from the periodic sweeper), and (c) fresh temps
survive the startup sweep.
publish_on_close integration tests and CI. Added a publish-on-close job to the interop CI workflow that runs the
impacket two-client scenario (A creates+writes, B lists+opens during
pending, host ls -A shows only temp, B closes → publish) and a
rclone --inplace test with inotifywait (asserting only MOVED_TO on
the final name). Transcripts are uploaded as CI artifacts. The nightly
smbtorture baseline now also runs with publish_on_close ON
(tests/live/rssmb-live-poc.toml) and compares against results-poc.md.
Fixed
publish_on_close: abort orphaning data on attach rollback. When
an attached handle (a second CREATE on a pending name) rolled back to
zero open_count via abort(), the temp file — carrying another
handle's written data — was orphaned (entry removed, temp left on
disk with no pending entry to publish it). abort() now returns (temp, delete_on_close) — the same shape as close() — and the rollback_on_err macro publishes the temp (rename → final) instead
of orphaning it. Only a freshly-created empty temp (created_here)
or a delete_on_close temp is unlinked.
publish_on_close: rename + take_destination not atomic. The
three-step rename → take_destination → rename dance held the
table-level write lock three separate times, leaving a window where
both source and destination were absent from the map. Replaced with rename_with_replace() — one method, one write lock, one atomic
table-level operation that does the move and collision handling
(including discarding a displaced destination) in a single lock hold.
publish_on_close: close race — rename under lock. The close()
path removed the pending entry and returned the temp path before the
caller performed the filesystem rename, leaving a window where a
racing resolve_or_acquire could miss the entry and create a phantom
re-pend. Replaced with close_publish() which calls the rename
closure under the table's write lock — the entry is removed
atomically with the filesystem rename, so no racing acquire can
observe the gap.
publish_on_close: attach race — no phantom entry. The
pending-file probe in LocalFs::create used resolve_or_acquire
which minted a Created entry and immediately aborted it, leaving a
window where a racing close or resolve_or_acquire could see the
phantom entry. Replaced with attach() which finds an existing
pending entry and increments its count, or returns None — no mint,
no abort, no phantom.
Credit window: credit_charge=0 consumed a MessageId. Per MS-SMB2
§3.3.1.2, credit_charge=0 MUST be treated as 1 for the credit
balance (available credits), but the MessageId sequence window
must use the actual credit_charge value (0 = no MessageIds
consumed). The server incorrectly treated credit_charge=0 as 1 for
both, consuming MessageId M for a zero-charge WRITE and then
rejecting a CLOSE with the same MessageId M as "already used".
Fixed by separating the balance charge (max(charge, 1)) from the
window charge (actual charge) in CreditManager::check_and_deduct.
Also added a balance-availability check so a zero-charge request with
no available credits still fails (instead of silently saturating to
0). This fixes the impacket smb.close()/logoff() connection
terminations that forced the publish-on-close integration test to
work around them by dropping the TCP socket.
Changed
multichannel default flipped to false. SMB 3.x multichannel is
now off by default until binding hardening lands; set multichannel = true
in the server config to re-enable. The server still honors the capability
when explicitly enabled.
Security
NTLMv2 timestamp freshness window (ntlm_max_clock_skew_secs,
default 600). When ntlm_require_timestamp is true, the MsvAvTimestamp
in the AUTHENTICATE message is now checked for freshness (±10 min by
default) against the server clock, not just presence. A stale timestamp
is rejected as a replay attempt. Set 0 for the old presence-only
behavior.