Skip to content

Commit 36991c1

Browse files
SeanHeelanSteve French
authored andcommitted
ksmbd: Fix UAF in __close_file_table_ids
A use-after-free is possible if one thread destroys the file via __ksmbd_close_fd while another thread holds a reference to it. The existing checks on fp->refcount are not sufficient to prevent this. The fix takes ft->lock around the section which removes the file from the file table. This prevents two threads acquiring the same file pointer via __close_file_table_ids, as well as the other functions which retrieve a file from the IDR and which already use this same lock. Cc: stable@vger.kernel.org Signed-off-by: Sean Heelan <seanheelan@gmail.com> Acked-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com>
1 parent 0ca6df4 commit 36991c1

File tree

1 file changed

+26
-7
lines changed

1 file changed

+26
-7
lines changed

fs/smb/server/vfs_cache.c

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -661,21 +661,40 @@ __close_file_table_ids(struct ksmbd_file_table *ft,
661661
bool (*skip)(struct ksmbd_tree_connect *tcon,
662662
struct ksmbd_file *fp))
663663
{
664-
unsigned int id;
665-
struct ksmbd_file *fp;
666-
int num = 0;
664+
struct ksmbd_file *fp;
665+
unsigned int id = 0;
666+
int num = 0;
667+
668+
while (1) {
669+
write_lock(&ft->lock);
670+
fp = idr_get_next(ft->idr, &id);
671+
if (!fp) {
672+
write_unlock(&ft->lock);
673+
break;
674+
}
667675

668-
idr_for_each_entry(ft->idr, fp, id) {
669-
if (skip(tcon, fp))
676+
if (skip(tcon, fp) ||
677+
!atomic_dec_and_test(&fp->refcount)) {
678+
id++;
679+
write_unlock(&ft->lock);
670680
continue;
681+
}
671682

672683
set_close_state_blocked_works(fp);
684+
idr_remove(ft->idr, fp->volatile_id);
685+
fp->volatile_id = KSMBD_NO_FID;
686+
write_unlock(&ft->lock);
687+
688+
down_write(&fp->f_ci->m_lock);
689+
list_del_init(&fp->node);
690+
up_write(&fp->f_ci->m_lock);
673691

674-
if (!atomic_dec_and_test(&fp->refcount))
675-
continue;
676692
__ksmbd_close_fd(ft, fp);
693+
677694
num++;
695+
id++;
678696
}
697+
679698
return num;
680699
}
681700

0 commit comments

Comments
 (0)