]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ksmbd: return oplock protocol error for level II ack
authorNamjae Jeon <linkinjeon@kernel.org>
Sun, 21 Jun 2026 10:49:41 +0000 (19:49 +0900)
committerSteve French <stfrench@microsoft.com>
Tue, 23 Jun 2026 01:15:06 +0000 (20:15 -0500)
SMB2 level II to none oplock breaks do not require an acknowledgment from
the client.  smb2.oplock.levelii500 intentionally acknowledges such a break
and expects the server to reject it with STATUS_INVALID_OPLOCK_PROTOCOL.

ksmbd drops the local level II oplock to none immediately after sending the
break notification because it does not wait for an ACK.  When the client
then sends the invalid ACK, smb20_oplock_break_ack() sees that the oplock
is not in OPLOCK_ACK_WAIT state and returns STATUS_INVALID_DEVICE_STATE
before checking the current oplock level.

If the oplock is already none when an unexpected SMB2 oplock break ACK
arrives, report STATUS_INVALID_OPLOCK_PROTOCOL.  Keep the existing
STATUS_INVALID_DEVICE_STATE response for other unexpected non-wait states.

Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/server/smb2pdu.c

index d4a40cede7bd0ef1647053aa8f25e7c9b0e18f7f..705cef655702b900c5bb498f9462342b4e73c103 100644 (file)
@@ -9225,7 +9225,10 @@ static void smb20_oplock_break_ack(struct ksmbd_work *work)
        if (opinfo->op_state != OPLOCK_ACK_WAIT) {
                ksmbd_debug(SMB, "unexpected oplock state 0x%x\n",
                            opinfo->op_state);
-               status = STATUS_INVALID_DEVICE_STATE;
+               if (opinfo->level == SMB2_OPLOCK_LEVEL_NONE)
+                       status = STATUS_INVALID_OPLOCK_PROTOCOL;
+               else
+                       status = STATUS_INVALID_DEVICE_STATE;
                goto err_out;
        }