summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNamjae Jeon <linkinjeon@kernel.org>2026-06-21 19:50:12 +0900
committerSteve French <stfrench@microsoft.com>2026-06-22 20:15:06 -0500
commit43f21349427dc964bfc7aa450e7e560f292698bb (patch)
treeba78f1ab984c77b8d1145c9ab099efa1936b6468
parent854b4f8f80f879aceead300028faeda8c90b4b91 (diff)
downloadlinux-next-43f21349427dc964bfc7aa450e7e560f292698bb.tar.gz
linux-next-43f21349427dc964bfc7aa450e7e560f292698bb.zip
ksmbd: normalize ungrantable lease states
smb2.lease.request verifies which SMB2 lease state combinations are granted by the server. Requests for H-only, W-only, and HW leases are valid lease state bitmasks, but they are not grantable combinations and should be returned as lease state none. ksmbd only checked that the requested bits were inside the SMB2 lease state mask. As a result it could grant H-only, W-only, or HW requests and return non-zero lease states where the client expects no lease. Keep the bitmask validation, but normalize ungrantable combinations to zero before allocating or looking up the lease. The grantable combinations remain unchanged: R, RH, RW, and RHW. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com>
-rw-r--r--fs/smb/server/oplock.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c
index 5abeb90ebebb..331ce10dbb66 100644
--- a/fs/smb/server/oplock.c
+++ b/fs/smb/server/oplock.c
@@ -29,6 +29,17 @@ static bool lease_state_valid(__le32 state)
return !(state & ~SMB2_LEASE_STATE_MASK_LE);
}
+static __le32 lease_state_grantable(__le32 state)
+{
+ if (state == SMB2_LEASE_READ_CACHING_LE ||
+ state == (SMB2_LEASE_READ_CACHING_LE | SMB2_LEASE_HANDLE_CACHING_LE) ||
+ state == (SMB2_LEASE_READ_CACHING_LE | SMB2_LEASE_WRITE_CACHING_LE) ||
+ state == SMB2_LEASE_STATE_MASK_LE)
+ return state;
+
+ return 0;
+}
+
static bool lease_v2_flags_valid(__le32 flags)
{
return !(flags & ~SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE);
@@ -1760,6 +1771,7 @@ struct lease_ctx_info *parse_lease_state(void *open_req)
if (!lease_state_valid(lreq->req_state) ||
!lease_v2_flags_valid(lreq->flags))
goto err_out;
+ lreq->req_state = lease_state_grantable(lreq->req_state);
if (lreq->flags == SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE)
memcpy(lreq->parent_lease_key, lc->lcontext.ParentLeaseKey,
SMB2_LEASE_KEY_SIZE);
@@ -1777,6 +1789,7 @@ struct lease_ctx_info *parse_lease_state(void *open_req)
lreq->duration = lc->lcontext.LeaseDuration;
if (!lease_state_valid(lreq->req_state))
goto err_out;
+ lreq->req_state = lease_state_grantable(lreq->req_state);
lreq->version = 1;
} else
goto err_out;