three ksmbd server fixes
-----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmoh6iQACgkQiiy9cAdy T1HZagv+PVKZ5Djru4YzKQH19sYHkiav7FLzwZZy+bTmGlApWci6m/7aBojZOeac t5vaFURjrrGSAY5QQGjtr7rFgsQsQkU6AuSo8BnaGXRdzf9HoMkI0TI/OOGfuELX BCD10yoX8m8SwnrXIPaqHoyfn0uhUHRZk8okWPtPzv19VZK3t84XkQjLjR+IYHwb UZWhmGanjqw2yS5kTuWr6M3+POLnDqrdEzNj8R1ugcQ5aH/s1vfVEUi1vXKnGSBa ZPldxXRUpbEUMwrk1PyXd4Hb/OKpQrAoj3kl6sBXLNvLHtiw4i8+NkpGDg00eXYE xOqAdADNFpWx1lIJVJ845Enn5twaGM8y7KlXr+lEGfVU7iCKahs4d0RkjQON5aTo 1HTx+nov4cP0nojvnPONU0li576E66ryqWzpBqsfEN93ROi+x7snuT9vB6QCjGHH lDv0UgsGF9TGWw2sBBQXhgYBXiFs2e1YSvdfT6KAd2x2SEJOIZ8yM6+ZNLzS1zTP XGjnnZ7S =7kge -----END PGP SIGNATURE----- Merge tag 'v7.1-rc7-ksmbd-server-fixes' of git://git.samba.org/ksmbd Pull smb server fixes from Steve French: - Fix use after free in SMB2_CANCEL - Fix race in ksmbd_reopen_durable_fd - Fix oplock and lease break potential NULL-dref * tag 'v7.1-rc7-ksmbd-server-fixes' of git://git.samba.org/ksmbd: ksmbd: fix use-after-free of a deferred file_lock on double SMB2_CANCEL ksmbd: fix durable reconnect double-bind race in ksmbd_reopen_durable_fd ksmbd: fix NULL-deref of opinfo->conn in oplock/lease break notifiers
This commit is contained in:
commit
e4a9638a0b
3 changed files with 32 additions and 6 deletions
|
|
@ -711,11 +711,16 @@ out:
|
|||
*/
|
||||
static int smb2_oplock_break_noti(struct oplock_info *opinfo)
|
||||
{
|
||||
struct ksmbd_conn *conn = opinfo->conn;
|
||||
struct ksmbd_conn *conn;
|
||||
struct oplock_break_info *br_info;
|
||||
int ret = 0;
|
||||
struct ksmbd_work *work = ksmbd_alloc_work_struct();
|
||||
struct ksmbd_work *work;
|
||||
|
||||
conn = READ_ONCE(opinfo->conn);
|
||||
if (!conn)
|
||||
return 0;
|
||||
|
||||
work = ksmbd_alloc_work_struct();
|
||||
if (!work)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -815,11 +820,15 @@ out:
|
|||
*/
|
||||
static int smb2_lease_break_noti(struct oplock_info *opinfo)
|
||||
{
|
||||
struct ksmbd_conn *conn = opinfo->conn;
|
||||
struct ksmbd_conn *conn;
|
||||
struct ksmbd_work *work;
|
||||
struct lease_break_info *br_info;
|
||||
struct lease *lease = opinfo->o_lease;
|
||||
|
||||
conn = READ_ONCE(opinfo->conn);
|
||||
if (!conn)
|
||||
return 0;
|
||||
|
||||
work = ksmbd_alloc_work_struct();
|
||||
if (!work)
|
||||
return -ENOMEM;
|
||||
|
|
|
|||
|
|
@ -7322,6 +7322,17 @@ int smb2_cancel(struct ksmbd_work *work)
|
|||
le64_to_cpu(hdr->Id.AsyncId))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* A cancelled deferred byte-range lock frees its
|
||||
* file_lock and takes the smb2_lock() early-exit that
|
||||
* skips release_async_work(), so the work stays on
|
||||
* conn->async_requests with a live cancel_fn pointing
|
||||
* at the freed file_lock. Re-firing it on a second
|
||||
* SMB2_CANCEL is a use-after-free.
|
||||
*/
|
||||
if (iter->state == KSMBD_WORK_CANCELLED)
|
||||
break;
|
||||
|
||||
ksmbd_debug(SMB,
|
||||
"smb2 with AsyncId %llu cancelled command = 0x%x\n",
|
||||
le64_to_cpu(hdr->Id.AsyncId),
|
||||
|
|
|
|||
|
|
@ -1390,19 +1390,19 @@ int ksmbd_reopen_durable_fd(struct ksmbd_work *work, struct ksmbd_file *fp)
|
|||
struct ksmbd_lock *smb_lock;
|
||||
unsigned int old_f_state;
|
||||
|
||||
write_lock(&global_ft.lock);
|
||||
if (!fp->is_durable || fp->conn || fp->tcon) {
|
||||
write_unlock(&global_ft.lock);
|
||||
pr_err("Invalid durable fd [%p:%p]\n", fp->conn, fp->tcon);
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
if (has_file_id(fp->volatile_id)) {
|
||||
write_unlock(&global_ft.lock);
|
||||
pr_err("Still in use durable fd: %llu\n", fp->volatile_id);
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
old_f_state = fp->f_state;
|
||||
fp->f_state = FP_NEW;
|
||||
|
||||
/*
|
||||
* Initialize fp's connection binding before publishing fp into the
|
||||
* session's file table. If __open_id() is ordered first, a
|
||||
|
|
@ -1413,11 +1413,17 @@ int ksmbd_reopen_durable_fd(struct ksmbd_work *work, struct ksmbd_file *fp)
|
|||
*/
|
||||
fp->conn = ksmbd_conn_get(conn);
|
||||
fp->tcon = work->tcon;
|
||||
write_unlock(&global_ft.lock);
|
||||
|
||||
old_f_state = fp->f_state;
|
||||
fp->f_state = FP_NEW;
|
||||
|
||||
__open_id(&work->sess->file_table, fp, OPEN_ID_TYPE_VOLATILE_ID);
|
||||
if (!has_file_id(fp->volatile_id)) {
|
||||
write_lock(&global_ft.lock);
|
||||
fp->conn = NULL;
|
||||
fp->tcon = NULL;
|
||||
write_unlock(&global_ft.lock);
|
||||
ksmbd_conn_put(conn);
|
||||
fp->f_state = old_f_state;
|
||||
return -EBADF;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue