mirror of
https://github.com/torvalds/linux.git
synced 2026-10-07 19:16:02 +02:00
ksmbd: safely discard unregistered deferred locks
When vfs_lock_file() defers a lock, smb2_lock() puts its ksmbd_lock on rollback_list before allocating and registering the asynchronous work. If either operation fails, rollback assumes that smb_lock->conn is initialized and dereferences NULL. The deferred file_lock also remains linked into the VFS blocked-lock state while it is freed. Keep the lock off rollback_list until async setup succeeds. On setup failures, explicitly unblock and wake the deferred lock before freeing it and its ksmbd wrapper. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
This commit is contained in:
parent
5ce5227cd6
commit
054bcca4cd
|
|
@ -9169,6 +9169,13 @@ static void smb2_remove_blocked_lock(void **argv)
|
|||
locks_wake_up(flock);
|
||||
}
|
||||
|
||||
static void smb2_free_blocked_lock(struct file_lock *flock)
|
||||
{
|
||||
ksmbd_vfs_posix_lock_unblock(flock);
|
||||
locks_wake_up(flock);
|
||||
locks_free_lock(flock);
|
||||
}
|
||||
|
||||
static inline bool lock_defer_pending(struct file_lock *fl)
|
||||
{
|
||||
/* check pending lock waiters */
|
||||
|
|
@ -9428,11 +9435,12 @@ int smb2_lock(struct ksmbd_work *work)
|
|||
|
||||
ksmbd_debug(SMB,
|
||||
"would have to wait for getting lock\n");
|
||||
list_add(&smb_lock->llist, &rollback_list);
|
||||
|
||||
argv = kmalloc(sizeof(void *), KSMBD_DEFAULT_GFP);
|
||||
if (!argv) {
|
||||
err = -ENOMEM;
|
||||
smb2_free_blocked_lock(flock);
|
||||
kfree(smb_lock);
|
||||
goto out;
|
||||
}
|
||||
argv[0] = flock;
|
||||
|
|
@ -9443,8 +9451,11 @@ int smb2_lock(struct ksmbd_work *work)
|
|||
if (rc) {
|
||||
kfree(argv);
|
||||
err = -ENOMEM;
|
||||
smb2_free_blocked_lock(flock);
|
||||
kfree(smb_lock);
|
||||
goto out;
|
||||
}
|
||||
list_add(&smb_lock->llist, &rollback_list);
|
||||
spin_lock(&fp->f_lock);
|
||||
list_add(&work->fp_entry, &fp->blocked_works);
|
||||
spin_unlock(&fp->f_lock);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user