From: Namjae Jeon Date: Sun, 21 Jun 2026 10:50:12 +0000 (+0900) Subject: ksmbd: normalize ungrantable lease states X-Git-Tag: v7.2-rc1~23^2~11 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=43f21349427dc964bfc7aa450e7e560f292698bb;p=thirdparty%2Fkernel%2Flinux.git 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 Signed-off-by: Steve French --- diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c index 5abeb90ebebb3..331ce10dbb669 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;