Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ksmbd: fix use-after-free in smb2_open during durable reconnect

In smb2_open, the call to ksmbd_put_durable_fd(fp) drops the reference
to the durable file descriptor early during the durable reconnect
process. If an error occurs subsequently (eg, ksmbd_iov_pin_rsp fails)
or a scavenger accesses the file, it leads to a use-after-free when
accessing fp properties (eg fp->create_time).

Move the single put to the end of the function below err_out2 so fp
stays valid until smb2_open returns.

Fixes: c8efcc786146 ("ksmbd: add support for durable handles v1/v2")
Signed-off-by: Akif <akif.sait111@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>

authored by

Akif and committed by
Steve French
1baff47b 3e4e2ea2

+5 -8
+5 -8
fs/smb/server/smb2pdu.c
··· 3014 3014 if (dh_info.reconnected == true) { 3015 3015 rc = smb2_check_durable_oplock(conn, share, dh_info.fp, 3016 3016 lc, sess->user, name); 3017 - if (rc) { 3018 - ksmbd_put_durable_fd(dh_info.fp); 3017 + if (rc) 3019 3018 goto err_out2; 3020 - } 3021 3019 3022 3020 rc = ksmbd_reopen_durable_fd(work, dh_info.fp); 3023 - if (rc) { 3024 - ksmbd_put_durable_fd(dh_info.fp); 3021 + if (rc) 3025 3022 goto err_out2; 3026 - } 3027 3023 3028 3024 fp = dh_info.fp; 3029 3025 3030 3026 if (ksmbd_override_fsids(work)) { 3031 3027 rc = -ENOMEM; 3032 - ksmbd_put_durable_fd(dh_info.fp); 3033 3028 goto err_out2; 3034 3029 } 3035 3030 3036 3031 file_info = FILE_OPENED; 3037 3032 3038 3033 rc = ksmbd_vfs_getattr(&fp->filp->f_path, &stat); 3039 - ksmbd_put_durable_fd(fp); 3040 3034 if (rc) 3041 3035 goto err_out2; 3042 3036 ··· 3799 3805 smb2_set_err_rsp(work); 3800 3806 ksmbd_debug(SMB, "Error response: %x\n", rsp->hdr.Status); 3801 3807 } 3808 + 3809 + if (dh_info.reconnected) 3810 + ksmbd_put_durable_fd(dh_info.fp); 3802 3811 3803 3812 kfree(name); 3804 3813 kfree(lc);