[PATCH] ksmbd: fix use-after-free in same_client_has_lease()

Guangshuo Li posted 1 patch 3 days, 2 hours ago
fs/smb/server/oplock.c | 6 ++++++
1 file changed, 6 insertions(+)
[PATCH] ksmbd: fix use-after-free in same_client_has_lease()
Posted by Guangshuo Li 3 days, 2 hours ago
same_client_has_lease() returns an opinfo pointer from ci->m_op_list
after dropping ci->m_lock without taking a reference.

smb_grant_oplock() then dereferences that pointer in copy_lease() and
when checking breaking_cnt. A concurrent close can remove the old lease
from ci->m_op_list and drop the last reference before the caller uses
the returned pointer, leading to a use-after-free.

Take a reference when same_client_has_lease() selects an existing lease,
drop any previous match while scanning, and release the returned
reference in smb_grant_oplock() after copying the lease state.

Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3")
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
---
 fs/smb/server/oplock.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c
index 0f5c18520eff..5e717aa03446 100644
--- a/fs/smb/server/oplock.c
+++ b/fs/smb/server/oplock.c
@@ -528,7 +528,12 @@ static struct oplock_info *same_client_has_lease(struct ksmbd_inode *ci,
 
 		ret = compare_guid_key(opinfo, client_guid, lctx->lease_key);
 		if (ret) {
+			if (!atomic_inc_not_zero(&opinfo->refcount))
+				continue;
+			if (m_opinfo)
+				opinfo_put(m_opinfo);
 			m_opinfo = opinfo;
+
 			/* skip upgrading lease about breaking lease */
 			if (atomic_read(&opinfo->breaking_cnt))
 				continue;
@@ -1237,6 +1242,7 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid,
 			if (atomic_read(&m_opinfo->breaking_cnt))
 				opinfo->o_lease->flags =
 					SMB2_LEASE_FLAG_BREAK_IN_PROGRESS_LE;
+			opinfo_put(m_opinfo);
 			goto out;
 		}
 	}
-- 
2.43.0
Re: [PATCH] ksmbd: fix use-after-free in same_client_has_lease()
Posted by Namjae Jeon 1 day, 19 hours ago
On Fri, Jun 5, 2026 at 1:30 PM Guangshuo Li <lgs201920130244@gmail.com> wrote:
>
> same_client_has_lease() returns an opinfo pointer from ci->m_op_list
> after dropping ci->m_lock without taking a reference.
>
> smb_grant_oplock() then dereferences that pointer in copy_lease() and
> when checking breaking_cnt. A concurrent close can remove the old lease
> from ci->m_op_list and drop the last reference before the caller uses
> the returned pointer, leading to a use-after-free.
>
> Take a reference when same_client_has_lease() selects an existing lease,
> drop any previous match while scanning, and release the returned
> reference in smb_grant_oplock() after copying the lease state.
>
> Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3")
> Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
Applied it to #ksmbd-for-next-next.
Thanks!