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

staging: android: ashmem: Fix possible deadlock in ashmem_ioctl

ashmem_mutex may create a chain of dependencies like:

CPU0 CPU1
mmap syscall ioctl syscall
-> mmap_sem (acquired) -> ashmem_ioctl
-> ashmem_mmap -> ashmem_mutex (acquired)
-> ashmem_mutex (try to acquire) -> copy_from_user
-> mmap_sem (try to acquire)

There is a lock odering problem between mmap_sem and ashmem_mutex causing
a lockdep splat[1] during a syzcaller test. This patch fixes the problem
by move copy_from_user out of ashmem_mutex.

[1] https://www.spinics.net/lists/kernel/msg2733200.html

Fixes: ce8a3a9e76d0 (staging: android: ashmem: Fix a race condition in pin ioctls)
Reported-by: syzbot+d7a918a7a8e1c952bc36@syzkaller.appspotmail.com
Signed-off-by: Yisheng Xie <xieyisheng1@huawei.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Yisheng Xie and committed by
Greg Kroah-Hartman
740a5759 a42ae590

+3 -5
+3 -5
drivers/staging/android/ashmem.c
··· 701 701 size_t pgstart, pgend; 702 702 int ret = -EINVAL; 703 703 704 + if (unlikely(copy_from_user(&pin, p, sizeof(pin)))) 705 + return -EFAULT; 706 + 704 707 mutex_lock(&ashmem_mutex); 705 708 706 709 if (unlikely(!asma->file)) 707 710 goto out_unlock; 708 - 709 - if (unlikely(copy_from_user(&pin, p, sizeof(pin)))) { 710 - ret = -EFAULT; 711 - goto out_unlock; 712 - } 713 711 714 712 /* per custom, you can pass zero for len to mean "everything onward" */ 715 713 if (!pin.len)