diff options
| author | Namjae Jeon <linkinjeon@kernel.org> | 2026-06-21 19:50:12 +0900 |
|---|---|---|
| committer | Steve French <stfrench@microsoft.com> | 2026-06-22 20:15:06 -0500 |
| commit | 43f21349427dc964bfc7aa450e7e560f292698bb (patch) | |
| tree | ba78f1ab984c77b8d1145c9ab099efa1936b6468 | |
| parent | 854b4f8f80f879aceead300028faeda8c90b4b91 (diff) | |
| download | linux-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.c | 13 |
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; |
