[BUG 3/3] smb: client: seal mount policy can be dropped after SMB3.1.1 reconnect
"Birtwhistle, Daniel" <[email protected]> Sun, 19 Jul 2026 18:09:20 +0000
| Newsgroups | org.kernel.vger.linux-cifs |
|---|---|
| Message-ID | <SN4PR22MB28886AB743AFFB419EFBA70EEEC42@SN4PR22MB2888.namprd22.prod.outlook.com> |
Resending in plain text because the original copy was rejected by linux-cifs due to Outlook always wanting talk html; apologies for the duplicate to direct recipients... Hello Steve, Paulo, and linux-cifs maintainers, My name is Daniel Birtwhistle. In my role, I assess security properties of software inherited by GE HealthCare products. I am writing personally as the researcher and technical contact. This is the third of three coordinated CIFS client reports. The first covers SMB2/3 response-signature enforcement, and the second asks for classification of server-provided symlink mount confinement. This message covers a separate SMB3 reconnect invariant and can be fixed and classified independently. Summary An SMB3.1.1 tree mounted with the explicit client option "seal" can reconnect to an otherwise authenticated endpoint that does not advertise encryption and continue in plaintext. The client logs "Encryption is requested but not supported", but reconnect TREE_CONNECT succeeds and later file I/O is no longer encrypted. Runtime confirmation I reproduced this on Linux 6.18.12+kali-arm64 with Samba 4.23.6, SMB 3.1.1, NTLMSSP, mandatory signing, and client options sign,seal. The first server supported AES-128-GCM but did not itself mandate encryption, so the client's seal option was the sole policy requirement. I then terminated the entire server service cgroup, including its per-client worker, and compared two replacements on a fresh TCP connection: - An encryption-capable replacement reconnected successfully, smb3_encryption_required() remained 1, and all post-reconnect application traffic remained in encrypted transform frames. - A replacement using the same test credential but omitting SMB2_ENCRYPTION_CAPABILITIES also reconnected successfully. The kernel logged the warning for both the data and IPC trees, smb3_encryption_required() changed to 0, both SMB2_tcon() calls returned 0, and a fixed canary was read through plaintext TREE_CONNECT, CREATE and READ messages. The matched packet captures each contain 88 packets. In the downgrade cell, the initial stream has 36 encrypted transform frames, while the replacement stream has none and its successful READ response visibly contains the fixed test canary. The capable control has ten encrypted transform frames on its replacement stream. Current source I rechecked upstream commit 980ab36ae5972c83f683b939e50c469c4947229e from 2026-07-19. Re-negotiate replaces the active server capability state. On reconnect, SMB2_tcon() logs when the existing tree requested sealing but the new server lacks encryption, without returning an error. smb3_encryption_required() then conditions the tree's seal request on that new capability and returns false, permitting the plaintext traffic observed above. The log-only reconnect check appears to have been introduced by ae6f8dd4d0c8 in 2016 and remains present at the current commit above, giving an affected source range from that introduction through current mainline. Scope and fix direction The terminal downgrade replacement deliberately knew the test credential. It isolates and directly proves the encryption-policy failure; it is not a claim that an unauthenticated replacement completed this exact end-to-end chain. Forged encrypted responses still fail AEAD authentication. The first companion report separately addresses bad-signature response acceptance and may compound with this behavior, but I am not representing the combined no-key sealed takeover as runtime-proven. The client invariant appears straightforward: an explicit must-seal policy should survive re-negotiate, and reconnect should fail closed if the replacement cannot satisfy it. It may also be prudent to reject plaintext responses while an active tree or session is under client-required sealing, instead of deciding only from the received header form. I built and differentially tested a candidate that rejects TREE_CONNECT before request construction when the retained client policy requires sealing but the new server cannot encrypt. On maintained 7.1.3+deb14-arm64, the capable replacement still completed its sealed reconnect and canary read. The capability-clearing replacement authenticated and established TCP, but every tree reconnect returned -EOPNOTSUPP and the plaintext canary was never returned. I have the candidate patch, guarded matched harness, raw captures, transcripts, function-return traces and a hash manifest. I have not posted or attached the reproducer here, but can provide the minimum evidence directly and can test a proposed fix. Please let me know how you would like this classified and whether maintained stable branches should receive the correction. Requested credit, if useful: Daniel Birtwhistle Best Regards, Daniel Birtwhistle Senior Director Product Security & Assessment